Query: Fix performance regression starting the loop for all fields.

Fixes a performance regression starting the loop after calling `WP_Query( [ 'fields' => 'all' ] )`. This changes how `WP_Query::the_post()` determines whether there is a need to traverse the posts for cache warming.

If IDs are queried, `WP_Query::$posts` is assumed to be an array of post IDs. If all fields are queried, `WP_Query::$posts` is assumed to be an array of fully populated post objects.

Follow up to [59919], [59937].

Props joemcgill, peterwilsoncc, SirLouen.
Fixes #56992.


Built from https://develop.svn.wordpress.org/trunk@59993


git-svn-id: http://core.svn.wordpress.org/trunk@59335 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Peter Wilson
2025-03-16 22:57:28 +00:00
parent 8e9d8e7bd4
commit 1523f87bc8
2 changed files with 44 additions and 26 deletions

View File

@@ -2067,6 +2067,15 @@ class WP_Query {
case 'id=>parent':
$fields = "{$wpdb->posts}.ID, {$wpdb->posts}.post_parent";
break;
case '':
/*
* Set the default to 'all'.
*
* This is used in `WP_Query::the_post` to determine if the
* entire post object has been queried.
*/
$q['fields'] = 'all';
// Falls through.
default:
$fields = "{$wpdb->posts}.*";
}
@@ -3739,28 +3748,30 @@ class WP_Query {
global $post;
if ( ! $this->in_the_loop ) {
// Get post IDs to prime incomplete post objects.
$post_ids = array_reduce(
$this->posts,
function ( $carry, $post ) {
if ( is_numeric( $post ) && $post > 0 ) {
// Query for post ID.
$carry[] = $post;
}
if ( 'all' === $this->query_vars['fields'] ) {
// Full post objects queried.
$post_objects = $this->posts;
} else {
if ( 'ids' === $this->query_vars['fields'] ) {
// Post IDs queried.
$post_ids = $this->posts;
} else {
// Only partial objects queried, need to prime the cache for the loop.
$post_ids = array_reduce(
$this->posts,
function ( $carry, $post ) {
if ( isset( $post->ID ) ) {
$carry[] = $post->ID;
}
if ( is_object( $post ) && isset( $post->ID ) ) {
// Query for object, either WP_Post or stdClass.
$carry[] = $post->ID;
}
return $carry;
},
array()
);
if ( $post_ids ) {
return $carry;
},
array()
);
}
_prime_post_caches( $post_ids, $this->query_vars['update_post_term_cache'], $this->query_vars['update_post_meta_cache'] );
$post_objects = array_map( 'get_post', $post_ids );
}
$post_objects = array_map( 'get_post', $post_ids );
update_post_author_caches( $post_objects );
}
@@ -3781,12 +3792,19 @@ class WP_Query {
$post = $this->next_post();
// Ensure a full post object is available.
if ( $post instanceof stdClass ) {
// stdClass indicates that a partial post object was queried.
$post = get_post( $post->ID );
} elseif ( is_numeric( $post ) ) {
// Numeric indicates that only post IDs were queried.
$post = get_post( $post );
if ( 'all' !== $this->query_vars['fields'] ) {
if ( 'ids' === $this->query_vars['fields'] ) {
// Post IDs queried.
$post = get_post( $post );
} elseif ( isset( $post->ID ) ) {
/*
* Partial objecct queried.
*
* The post object was queried with a partial set of
* fields, populate the entire object for the loop.
*/
$post = get_post( $post->ID );
}
}
// Set up the global post object for the loop.

View File

@@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
$wp_version = '6.8-beta2-59992';
$wp_version = '6.8-beta2-59993';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.