WordPress 6.8 includes some caching optimizations that may affect themes and plugins using the WP_Query::get()
method and the WP_Query::$query_vars
property.
In #59516, WP_Query
was optimized to improve cache hits for queries with equivalent arguments.
This enhancement Enhancements are simple improvements to WordPress, such as the addition of a hook, a new feature, or an improvement to an existing feature. improves performance for sites that run equivalent queries with a different order of arguments. The impact will be most noticeable on sites without a persistent cache, as these equivalent queries would run multiple times on a single page request, whereas they will now run once.
As such theme and plugin 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 authors making use of filters within WP_Query
(source code: GitHub, trac) are recommended to check their code for compatibility with WordPress 6.8. An example of code that would be affected by this is using equality to check for the contents of an array:
$query = new WP_Query( array( 'post_type' => array( 'post', 'page' ) ) );
add_filter( 'posts_where', function ( $where, $query ) {
// True in WordPress 6.7, false in WordPress 6.8
// WordPress 6.7 returns array( 'post', 'page' )
// WordPress 6.8 returns array( 'page', 'post' )
if ( array( 'post', 'page' ) === $query->get( 'post_type' ) ) {
// Modify WHERE clause.
}
return $where;
}, 10, 2 );
When comparing the contents of two arrays for equivalence, it is recommended to use the code empty( array_diff( /* arrays */ ) )
rather than equality comparisons. See this example for a demonstration.
Standardized arguments.
The most common example of where these changes will improve performance is when querying multiple post types:
$q1 = new WP_Query( [ 'post_type' => [ 'post', 'page' ] ] );
$q2 = new WP_Query( [ 'post_type' => [ 'page', 'post'] ] );
$q3 = new WP_Query( [ 'post_type' => [ 'page', 'post', 'post' ] ] );
In WordPress 6.7 and earlier, these queries would each result in database queries as they were not seen as equivalent in the resulting database query and cache key.
To standardize equivalent queries, WP_Query
now sorts and type casts arguments as appropriate. For each of the queries above the post types are sorted alphabetically and any duplicates removed. In WordPress 6.8 the ::get()
method and ::$query_vars
property will differ from the arguments passed to $q1
and $q3
:
$q1->get( 'post_type' ) // returns [ 'page', 'post' ]
$q2->get( 'post_type' ) // returns [ 'page', 'post' ]
$q3->get( 'post_type' ) // returns [ 'page', 'post' ]
$q1->query_vars['post_type'] === [ 'page', 'post' ]
$q2->query_vars['post_type'] === [ 'page', 'post' ]
$q3->query_vars['post_type'] === [ 'page', 'post' ]
For items that accept values as either an integer or a string, these have been sorted and typecast as appropriate, for example author__not_in => [ '2', '1' ]
becomes author__not_in => [ 1, 2 ]
. A full list of affected arguments can be found in the commit message [59766].
Due to differences in the code paths when the post type and status are passed as a string, these are not type cast to an array
$q4 = new WP_Query( [ 'post_type' => 'post' ] );
$q4->get( 'post_type' ) // returns 'post'
These changes are part of an ongoing effort to improve the performance of WordPress. The core Core is the set of software required to run WordPress. The Core Development Team builds WordPress. team are monitoring the changes for any major issues that may occur, see #63255.
Props @joemcgill and @jorbin for their review of this post.
#6-8, #dev-notes, #dev-notes-6-8, #performance