New option functions in 6.4

WordPress 6.4 introduces a number of new functions related to options, with a particular focus on autoloaded options.

While options are autoloaded by default, based on the $autoload parameter of add_option() and update_option(), autoloading too many options is a common cause for slow server response time as well as bugs while using a persistent object cache.

To help pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party developers improve managing their plugins’ options, their performance, and whether to autoload them, two sets of functions are being introduced in 6.4:

  • wp_prime_option_caches() and related wrapper functions can be used to fetch multiple options with a single database query. Update: When this dev notedev note Each important change in WordPress Core is documented in a developers note, (usually called dev note). Good dev notes generally include a description of the change, the decision that led to this change, and a description of how developers are supposed to work with that change. Dev notes are published on Make/Core blog during the beta phase of WordPress release cycle. Publishing dev notes is particularly important when plugin/theme authors and WordPress developers need to be aware of those changes.In general, all dev notes are compiled into a Field Guide at the beginning of the release candidate phase. was first published, the function was named prime_options(), however that name was since revised to wp_prime_option_caches().
  • wp_set_option_autoload_values() and related wrapper functions can be used to update one or more specific options’ autoload values, independently of their option values.

New functions to retrieve multiple options in a single database query

The wp_prime_option_caches( $options ) function expects an array of option names, and then fetches any options that aren’t already cached with a single database query. The options are then stored in the cache so that subsequent get_option() calls for any of those options do not result in separate database queries.

Note that wp_prime_option_caches() does not return the options as its sole responsibility is to update the relevant caches. In order to actually retrieve multiple options at once, a new wrapper function get_options( $options ) has been introduced. It calls wp_prime_option_caches() for the option names given and then get_option() for every individual option, returning an associative array of option names and their values.

Last but not least, a third function wp_prime_option_caches_by_group() is being introduced, which primes all options of a specific option group (the mandatory first parameter of register_setting()). This can be helpful for plugins to fetch all options of a specific option group the plugin uses.

All of the above functions have been introduced not only as a performant way to retrieve multiple options from the database, but also as an alternative to autoloading options that are only needed in a few specific areas. For example, a plugin that currently autoloads a few options which are only used on the plugin’s own WP Adminadmin (and super admin) screen would be encouraged to use the new wp_prime_option_caches() or wp_prime_option_caches_by_group() instead of autoloading the options.

Example

In this example, we assume a plugin has a WP Admin screen that relies on four options: “myplugin_foo”, “myplugin_bar”, “myplugin_foobar”, and “myplugin_barfoo”. All of these options are only used on that admin screen and therefore should not be autoloaded. In other words, any add_option() and update_option() calls for those options should provide “no” for the $autoload parameter.

function myplugin_prime_admin_screen_options() {
	/*
	 * By priming the options here, no further database queries will be used
	 * when later calling `get_option()`.
	 */
	wp_prime_option_caches(
		array( 'myplugin_foo', 'myplugin_bar', 'myplugin_foobar', 'myplugin_barfoo' )
	);
}

function myplugin_add_admin_screen() {
	$hook_suffix = add_menu_page( /* Menu page arguments. */ );
	add_action( "load-{$hook_suffix}", 'myplugin_prime_admin_screen_options' );
}
add_action( 'admin_menu', 'myplugin_add_admin_screen' );

This code would ensure that the options are retrieved in a single database query. Any subsequent get_option() calls for these options would then not result in another database query and thus be extremely fast. As such, the WP Admin screen is just as performant as it would have been with autoloading those options, yet without unnecessarily slowing down performance of the entire site.

To further enhance that example, the plugin could rely on a single option group for which it registers those options. Here is the example code for that:

function myplugin_register_settings() {
	register_setting(
		'myplugin_admin_screen',
		'myplugin_foo',
		array( /* Registration arguments. */ )
	);
	register_setting(
		'myplugin_admin_screen',
		'myplugin_bar',
		array( /* Registration arguments. */ )
	);
	register_setting(
		'myplugin_admin_screen',
		'myplugin_foobar',
		array( /* Registration arguments. */ )
	);
	register_setting(
		'myplugin_admin_screen',
		'myplugin_barfoo',
		array( /* Registration arguments. */ )
	);
}
add_action( 'init', 'myplugin_register_settings' );

function myplugin_prime_admin_screen_options() {
	/*
	 * By priming the options here, no further database queries will be used
	 * when later calling `get_option()`.
	 */
	wp_prime_option_caches_by_group( 'myplugin_admin_screen' );
}

// `myplugin_add_admin_screen()` would remain as in the previous code example.

With that adjustment, the option registration would be the central place to manage the options, and the myplugin_prime_admin_screen_options() function would remain simple without maintaining a list of the exact options.

Please refer to TracTrac An open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress. ticketticket Created for both bug reports and feature development on the bug tracker. #58962 for additional details on these changes.

New functions to set option autoload values

The wp_set_option_autoload_values( array $options ) function expects an associative array of option names and their autoload values to set, and then updates those options’ autoload values in a single database query.

Additionally, two wrapper functions for the above are also being introduced for ease of use:

  • wp_set_options_autoload( $options, $autoload ) can be used to set multiple options to the same autoload value.
  • wp_set_option_autoload( $option, $autoload ) can be used to set the autoload value for a single option.

These functions can be useful in a plugin deactivation hook: After deactivation, the plugin’s options won’t be used anymore, yet they should not be deleted from the database until the user decides to uninstall the plugin.

Example

In this example, we assume a plugin has two options “myplugin_foo” and “myplugin_bar”, both of which are used in various frontend page loads and therefore autoloaded by default. To properly clean up after itself, such a plugin could implement usage of the new functions as follows:

function myplugin_activate() {
	wp_set_options_autoload(
		array( 'myplugin_foo', 'myplugin_bar' ),
		'yes'
	);
}
register_activation_hook( __FILE__, 'myplugin_activate' );

function myplugin_deactivate() {
	wp_set_options_autoload(
		array( 'myplugin_foo', 'myplugin_bar' ),
		'no'
	);
}
register_deactivation_hook( __FILE__, 'myplugin_deactivate' );

This code would ensure that the options are no longer autoloaded when the plugin has been deactivated. If the plugin gets (re-)activated, the options will be set to autoload again if they are already in the database.

Please refer to Trac ticket #58964 for additional details on these changes.

Related autoload bugbug A bug is an error or unexpected result. Performance improvements, code optimization, and are considered enhancements, not defects. After feature freeze, only bugs are dealt with, with regressions (adverse changes from the previous version) being the highest priority. fix for update_option()

While not directly tied to the above functions, it is worth noting that a bug relevant to autoloading has been addressed in 6.4: When using the $autoload parameter of update_option() alongside an option value update, the function would update the incorrect cache, not respecting the new autoload value. This could have severe implications such as returning a stale option value when the option in fact had already been deleted.

This bug has been fixed in 6.4, so that the $autoload parameter of update_option() can now be reliably used to change the option’s autoload value. It should be noted though that depending on the use-case the above functions to set option autoload values may be more suitable.

Please refer to Trac ticket #51352 for additional details on this bug fix.

Props to @westonruter and @webcommsat for review and proofreading.

#6-4, #dev-notes, #dev-notes-6-4, #performance