Object Cache in WordPress

Object cache or Object Cache in WordPress is a core mechanism that allows you to store any data in the cache. This cache is used to store data that is retrieved multiple times during code execution or to store data obtained after complex operations.

Example of Object Caching

Let's consider an example of caching an SQL query.

Suppose we have the following function. If this function is called multiple times in a row, it will execute the database query each time.

function myfunc() {
	return $wpdb->get_results( "SELECT ..." );
}

myfunc(); // SQL query
myfunc(); // SQL query
myfunc(); // SQL query

Let's make the function work with object cache. Now only the first call to the function will execute the SQL query, and the others will fetch data from the cache.

function myfunc() {
	global $wpdb;

	// try to get the cache and return it if it exists
	$cache_key = 'my_cache_key';
	$cache = wp_cache_get( $cache_key );

	if( false !== $cache )
		return $cache;

	$value = $wpdb->get_results( "SELECT ..." );

	wp_cache_set( $cache_key, $value ); // add data to the cache

	return $value;
}

myfunc(); // SQL query
myfunc(); // Cache
myfunc(); // Cache

Object Caching in WordPress

In WP, such caching is used almost everywhere: in options, posts, terms, users, metadata, etc.

Object Caching in WordPress Options

For example, let's consider how object caching works in WordPress options. The get_option() function does not create additional database queries on multiple calls, thanks to this cache.

When the function get_option() is called for the first time, the function wp_load_alloptions() is triggered, which loads all site options (with the autoload flag) from the database into the object cache. Now any subsequent calls to the get_option() function will not make database queries but will fetch data from the cache.

For instance, the following code called in the theme file will not make any database queries:

if( ! get_option( 'comments_open' ) ){
	echo '<p>Commenting on the site '. get_option('blogname') .' is closed.</p>';
	echo '<p>Contact the administration: '. get_option('admin_email') .'</p>';
}
Metadata Caching

The caching of metadata works on the same principle. For example, when retrieving posts using get_posts(), the data of posts and their metadata are cached. Therefore, subsequent requests for data of already processed posts will not make additional database queries.

// suppose this query returned posts: 1 2 3 4 5
$posts = get_posts();
foreach( $posts as $post ){
	echo esc_html( $post->post_title ) . '<br>';
}

// later in the code we need the metadata of post 3

echo get_post_meta( 3, 'my_meta', 1 ); // this data will be taken from the cache.

Persistent Object Caching

By default, object caching in WordPress is non-persistent — this means that it works within a single HTTP request (only for generating one page) and does not work between different requests (when visiting a new page, the cache from the old page is not used). During the page generation, data is stored in the cache (RAM) and fetched from there when the same data is requested again in the code. For example, this is why the get_option() function does not make a database query every time on subsequent calls but retrieves data from the object cache instead.

WordPress has the option to enable an external storage for object cache, thus making object caching persistent. This way, the data from the cache will work between requests.

To enable persistent object caching, you need to install a plugin. There are several such plugins because there are also various options for where to store such cache, here are some of them:

To determine whether persistent caching is used, WordPress employs the function wp_using_ext_object_cache(). It is useful for developers when different actions need to be performed depending on the presence or absence of a caching plugin.

For example, let's save a value in the object cache only if the cache is persistent; otherwise, let's save the value to a file:

if( wp_using_ext_object_cache() ){
	wp_cache_set( 'key', 'value' );
}
else {
	// your code to save data to a file
}

Groups

The $group parameter in caching functions allows the use of identical cache keys.

A group is a prefix for the key. This prefix is used:

  • when working with WordPress multisite ("global" and "non-global" groups).
  • when using object caching plugins ("persistent" and "non-persistent" groups).

The following group names are used in WordPress (you can also use them if they fit logically, otherwise name the group differently):

Group Name Description
(taxonomy)_relationships array of term_id
count stores counters
category -
posts stores posts
comment cache group for comments.
default default cache group.
options cache group for storing options.
themes cache groups for storing themes.
plugins cache groups for storing plugins.
users cache group for storing user information.
userlogins -
useremail -
userslugs -
transient stores temporary options - set_transient()
networks -
blog-details -
site-options -
sites found sites
site-transient stores temporary options - set_site_transient()
customize_changeset_post -
oembed_cache_post -
timeinfo -
calendar -

Global Groups (for Multisite)

They only work when WordPress is installed as a multisite network.

These groups include cache that is unified for the entire network.

For each site in the network, a site prefix is added to the cache key to distinguish, for example, the cache of a post with ID 5 from one site from the cache of a post with the same ID 5 from another site. However, there are also objects in multisite that work for the entire network, such as "Users" — these belong to global groups, and no prefix is added to the cache of such objects.

By default, the global groups are:

users
userlogins
usermeta
user_meta
useremail
userslugs
site-transient
site-options
blog-lookup
blog-details
site-details
rss
global-posts
blog-id-cache
networks
sites
themes

You can add your own group to the list of global groups, see the function wp_cache_add_global_groups('my-global-group').

Non-Persistent Groups

By default, all object caching in WordPress is non-persistent, i.e., caching occurs only during the page generation. However, if you install an object caching plugin, the cache will be retained between requests (e.g., in files) and will become persistent.

Sometimes you need the cache not to be retained permanently but to work as before (only during page generation). To achieve this, you can specify a group for the created object cache and mark this group as "Non-Persistent." This is done using the function wp_cache_add_non_persistent_groups( 'my-group' ).

Thus, when saving the cache in the group "my-group," the value will only be saved in the local cache (in RAM) and will not be stored in the cache plugin's storage, for example, on the Memcached server.

Usually, the following groups are considered non-persistent:

counts
plugins
themes

Disabling Object Cache

Disabling for a Code Section

Sometimes it is necessary to disable object caching, for example, when importing a large number of records into the database, and the normal execution of the code hits the memory limit on the server. This happens because each added record is stored in the cache, and for a one-time operation, this is unnecessary.

The function wp_suspend_cache_addition() can be used to temporarily disable object caching.

wp_suspend_cache_addition( true ); // disable object caching

// our code...

wp_suspend_cache_addition( false ); // enable it back

Completely Disabling Object Caching

Object caching plugins add a special file object-cache.php. To disable the operation of such a plugin on the fly, you can use the hook enable_loading_object_cache_dropin:

add_filter( 'enable_loading_object_cache_dropin', '__return_false' );

The hook appeared in WP version 5.8. It triggers before plugins are loaded and is needed when the code runs not from the web, for example, during tests.

How to Check if Object Cache is Enabled?

You can do this using the function wp_using_ext_object_cache():

if ( wp_using_ext_object_cache() ) {

	// add data to the cache
}

PHP Functions

wp_cache_get( $key, $group, $force, $found )
Retrieves the object cache data by specified cache key and group.
wp_cache_add( $key, $data, $group, $expire )
Adds data to the cache, if the cache key doesn't already exist.
wp_cache_set( $key, $data, $group, $expire )
Saves the data to the object cache. If data with this key already exists, it will be overwritten.
wp_cache_replace( $key, $data, $group, $expire )
Replaces the contents of the cache with new data.
wp_cache_delete( $key, $group )
Removes the cache contents matching key and group.
wp_cache_flush( )
Completely clears the object cache. Deletes all items in the object cache.
wp_cache_flush_group( $group )
Removes all cache items in a group, if the object cache implementation supports it.
wp_cache_add_global_groups( $groups )
Adds a group or set of groups to the list of global groups.
wp_cache_add_non_persistent_groups( $groups )
Adds a group or set of groups to the list of non-persistent groups.
wp_suspend_cache_addition( $suspend )
Temporarily suspends cache additions. It means that you can't add new objects to the cache after using this function.
wp_using_ext_object_cache( $using )
Toggle $_wp_using_ext_object_cache on and off without directly touching global.
wp_cache_supports( $feature )
Determines whether the object cache implementation supports a particular feature.
Wrapper Functions:
wp_cache_get_multiple( $keys, $group, $force )
Retrieves multiple values from the cache in one call.
wp_cache_add_multiple( $data, $group, $expire )
Adds multiple values to the cache in one call.
wp_cache_set_multiple( $data, $group, $expire )
Sets multiple values to the cache in one call.
wp_cache_delete_multiple( $keys, $group )
Deletes multiple values from the cache in one call.
wp_cache_flush_runtime( )
Removes all cache items from the in-memory runtime cache.

Full list of object cache functions.

Debugging Object Cache

To see how the cache is used, you can install the "Debug Bar" plugin. It allows you to view statistics on object cache accesses and memory consumption (how much a cache item weighs).

If an object caching plugin is installed, Debug Bar will show data from the external server.

--

The material was written using information from wpmag.ru.