Cache Hooks
Actions and filters related to the WordPress Object Cache.
Source: Various WordPress core files
Overview
The Object Cache API itself has minimal hooks. Most cache-related hooks are in components that use the cache (posts, terms, users, etc.). This document covers hooks that directly affect caching behavior.
Cache Suspension
wp_suspend_cache_addition
Filter that determines whether to suspend cache additions.
apply_filters( 'wp_suspend_cache_addition', bool $suspend ): bool
Location: wp-includes/functions.php (wp_suspend_cache_addition())
When suspended, wp_cache_add() returns false without adding data.
Parameters:
| Name | Type | Description |
|---|---|---|
$suspend |
bool |
Current suspension state |
Example:
// Temporarily suspend cache additions during import
add_filter( 'wp_suspend_cache_addition', '__return_true' );
// Do bulk import...
wp_insert_post( $post_data ); // Won't cache
// Re-enable
remove_filter( 'wp_suspend_cache_addition', '__return_true' );
Related Function:
/**
* Suspends cache additions.
*
* @param bool $suspend Optional. Suspends cache if true, enables if false.
* @return bool Previous suspend setting.
*/
function wp_suspend_cache_addition( $suspend = null ) {
static $_suspend = false;
if ( is_bool( $suspend ) ) {
$_suspend = $suspend;
}
return $_suspend;
}
wp_suspend_cache_invalidation
Filter that determines whether to suspend cache invalidation.
apply_filters( 'wp_suspend_cache_invalidation', bool $suspend ): bool
Location: wp-includes/functions.php (wp_suspend_cache_invalidation())
When suspended, cache invalidation functions (like those triggered by post updates) are skipped.
Parameters:
| Name | Type | Description |
|---|---|---|
$suspend |
bool |
Current suspension state |
Example:
// Suspend invalidation during bulk operations
wp_suspend_cache_invalidation( true );
foreach ( $posts as $post ) {
wp_update_post( $post ); // Won't trigger cache clearing
}
wp_suspend_cache_invalidation( false );
// Manually invalidate once at the end
wp_cache_flush_group( 'posts' );
Object Cache Actions
The core WP_Object_Cache class doesn’t fire actions, but persistent cache drop-ins may add their own. Common patterns:
Custom: object_cache_init
do_action( 'object_cache_init', WP_Object_Cache $cache );
Fired after cache connection is established (custom drop-in hook).
Custom: object_cache_flush
do_action( 'object_cache_flush' );
Fired when cache is flushed (custom drop-in hook).
Cache Priming Hooks
These core hooks are useful for warming the cache:
pre_get_posts
add_action( 'pre_get_posts', function( $query ) {
// Prime cache before main query
} );
wp_loaded
add_action( 'wp_loaded', function() {
// Prime frequently-accessed data
wp_cache_set( 'site_config', get_complex_config(), 'my_plugin' );
} );
Core Cache Invalidation Points
While not hooks themselves, these functions trigger cache clearing and are hooked by core:
Post Cache
// After post is updated/deleted
clean_post_cache( $post_id );
Clears: posts, post_meta, related term caches
Term Cache
// After term is updated/deleted
clean_term_cache( $term_ids, $taxonomy );
Clears: terms, term_meta, term relationship caches
User Cache
// After user is updated/deleted
clean_user_cache( $user_id );
Clears: users, user_meta, userlogins, useremail, userslugs
Options Cache
// Options are cached in 'alloptions' key
// Automatically invalidated on add/update/delete_option()
Cache-Related Filters
pre_wp_cache_* (Custom Pattern)
Some drop-ins implement filters to intercept cache operations:
// Example from custom drop-in
add_filter( 'pre_wp_cache_get', function( $value, $key, $group, $force, $found ) {
// Custom logic before cache get
return $value;
}, 10, 5 );
notoptions
When an option doesn’t exist, it’s recorded in the notoptions cache to prevent repeated DB lookups:
// Core uses this pattern
$notoptions = wp_cache_get( 'notoptions', 'options' );
if ( isset( $notoptions[ $option ] ) ) {
return $default; // Known to not exist
}
Transient Hooks
Transients use the Object Cache when available. Related hooks:
setted_transient
do_action( 'setted_transient', string $transient, mixed $value, int $expiration );
Fired after transient is set.
deleted_transient
do_action( 'deleted_transient', string $transient );
Fired after transient is deleted.
pre_transient_{$transient}
apply_filters( "pre_transient_{$transient}", mixed $pre_transient, string $transient );
Short-circuits transient retrieval.
transient_{$transient}
apply_filters( "transient_{$transient}", mixed $value, string $transient );
Filters transient value after retrieval.
Multisite Cache Hooks
switch_blog
do_action( 'switch_blog', int $new_blog_id, int $prev_blog_id );
Triggers wp_cache_switch_to_blog() to update cache key prefixes.
Implementing Custom Cache Hooks
When building a persistent cache drop-in, consider adding hooks:
class My_Object_Cache extends WP_Object_Cache {
public function set( $key, $data, $group = 'default', $expire = 0 ) {
/**
* Fires before data is cached.
*
* @param string $key Cache key.
* @param mixed $data Data to cache.
* @param string $group Cache group.
* @param int $expire Expiration in seconds.
*/
do_action( 'pre_object_cache_set', $key, $data, $group, $expire );
$result = parent::set( $key, $data, $group, $expire );
/**
* Fires after data is cached.
*
* @param string $key Cache key.
* @param mixed $data Cached data.
* @param string $group Cache group.
* @param bool $result Whether set succeeded.
*/
do_action( 'object_cache_set', $key, $data, $group, $result );
return $result;
}
public function flush() {
/**
* Fires before cache is flushed.
*/
do_action( 'pre_object_cache_flush' );
$result = parent::flush();
/**
* Fires after cache is flushed.
*/
do_action( 'object_cache_flush' );
return $result;
}
}
Debug & Monitoring Hooks
qm/collect (Query Monitor)
If using Query Monitor, cache data is collected automatically. Custom data:
add_filter( 'qm/collect/cache', function( $cache_data ) {
$cache_data['my_metric'] = get_my_cache_metric();
return $cache_data;
} );
Best Practices
Invalidating Custom Cache
// Hook into post save to invalidate related cache
add_action( 'save_post', function( $post_id ) {
wp_cache_delete( 'my_computed_data_' . $post_id, 'my_plugin' );
wp_cache_delete( 'related_posts_' . $post_id, 'my_plugin' );
} );
Warming Cache on Cron
add_action( 'my_plugin_warm_cache', function() {
$expensive_data = compute_expensive_data();
wp_cache_set( 'expensive_data', $expensive_data, 'my_plugin', DAY_IN_SECONDS );
} );
// Schedule if not already
if ( ! wp_next_scheduled( 'my_plugin_warm_cache' ) ) {
wp_schedule_event( time(), 'daily', 'my_plugin_warm_cache' );
}
Conditional Cache Bypass
add_filter( 'pre_transient_my_data', function( $value ) {
// Bypass cache for admins
if ( current_user_can( 'manage_options' ) && isset( $_GET['nocache'] ) ) {
return compute_fresh_data();
}
return $value;
} );