I have created a plugin that caches some of the data it uses - mainly Salesforce REST API call results, and expires them at intervals (by default every 24 hours).
The plugin calls these methods to control the caching:
/**
* Check to see if this API call exists in the cache
* if it does, return the transient for that key
*
* @param string $url The API call we'd like to make.
* @param array $args The arguents of the API call.
* @return get_transient $cachekey
*/
public function cache_get( $url, $args ) {
if ( is_array( $args ) ) {
$args[] = $url;
array_multisort( $args );
} else {
$args .= $url;
}
$prefix = esc_sql( $this->transient_prefix() );
$cachekey = $prefix . md5( wp_json_encode( $args ) );
return get_transient( $cachekey );
}
/**
* Create a cache entry for the current result, with the url and args as the key
*
* @param string $url The API query URL.
* @param array $args The arguments passed on the API query.
* @param array $data The data received.
* @param string $cache_expiration How long to keep the cache result around for.
* @return Bool whether or not the value was set
* @link https://developer.wordpress.org/reference/functions/set_transient/
*/
public function cache_set( $url, $args, $data, $cache_expiration = '' ) {
if ( is_array( $args ) ) {
$args[] = $url;
array_multisort( $args );
} else {
$args .= $url;
}
$prefix = esc_sql( $this->transient_prefix() );
$cachekey = $prefix . md5( wp_json_encode( $args ) );
// Cache_expiration is how long it should be stored in the cache.
// If we didn't give a custom one, use the default.
if ( '' === $cache_expiration ) {
$cache_expiration = $this->options['cache_expiration'];
}
return set_transient( $cachekey, $data, $cache_expiration );
}
/**
* Get the cache transient prefix for this plugin and return it
*
* @return The transient prefix
*/
private function transient_prefix() {
$transient_prefix = 'sfwp';
return $transient_prefix;
}
/**
* If there is a WordPress setting for how long to keep this specific cache, return it and set the object property
* Otherwise, return seconds in 24 hours
*
* @param string $option_key The cache item to keep around.
* @param int $expire The default time after which to expire the cache.
* @return The cache expiration saved in the database.
*/
public function cache_expiration( $option_key, $expire ) {
$cache_expiration = get_option( $option_key, $expire );
return $cache_expiration;
}
I'd like to provide users with a way to clear this cache manually though, in the event that they change up the configuration of their Salesforce objects and don't want to wait for the automatic expire. I'd like to avoid clearing the entire site's cache in this event though (this is my understanding of what wp_cache_flush()
would do).
I've just added the $transient_prefix
in the methods above, as I am realizing that this would be easy if the site is just using the Transients API. But if they're using an object cache, I'm out of my league.
I've created a cache_purge
method like this:
/**
* Create a cache entry for the current result, with the url and args as the key
*
* @param string $subset If we only want to purge WordPress data, Salesforce data, options, etc.
* @return Bool whether or not the purge was successful
*/
public function cache_purge( $subset = '' ) {
$prefix = esc_sql( $this->transient_prefix() );
// cache is stored somewhere other than the options table
if ( wp_using_ext_object_cache() ) {
} else {
// cache is stored in the options table. this is pretty easy.
$options = $this->wpdb->options;
$t = esc_sql( '_transient_timeout_' . $prefix . '%' );
$sql = $wpdb ->prepare( "SELECT option_name FROM $options WHERE option_name LIKE '%s'", $t );
$transients = $this->wpdb->get_col( $sql );
foreach ( $transients as $transient ) {
// Strip away the WordPress prefix in order to arrive at the transient key.
$key = str_replace( '_transient_timeout_', '', $transient );
// Now that we have the key, use WordPress core to the delete the transient.
delete_transient( $key );
}
}
}
My understanding is that this would let me check for the existence of any external object cache (which I think would cover the caching plugins, as well as Varnish/memcache/etc.) and if there's not one, clear the transients API.
Am I correct so far? If so, what can I do to clear the same data from an object cache?