[wp-trac] [WordPress Trac] #56992: The Loop displays incorrect data for queries started with `fields => 'id=>parent'`.

WordPress Trac noreply at wordpress.org
Fri Mar 14 20:49:21 UTC 2025


#56992: The Loop displays incorrect data for queries started with `fields =>
'id=>parent'`.
--------------------------------------+----------------------------
 Reporter:  peterwilsoncc             |       Owner:  peterwilsoncc
     Type:  defect (bug)              |      Status:  reopened
 Priority:  normal                    |   Milestone:  6.8
Component:  Query                     |     Version:  3.1
 Severity:  normal                    |  Resolution:
 Keywords:  has-patch has-unit-tests  |     Focuses:  performance
--------------------------------------+----------------------------
Changes (by SirLouen):

 * keywords:  dev-feedback has-patch has-unit-tests => has-patch has-unit-
     tests


Comment:

 Replying to [comment:44 peterwilsoncc]:
 > I've put together a [https://github.com/WordPress/wordpress-
 develop/pull/8495/files#diff-
 1d050668621cbc3028e027d15e68438f4d879dd6e80ba98f9c9f69b9fb5469d0 PR to
 change how it's determined whether the method needs to walk the array] of
 posts for cache warming of posts and author caches.

 Have you found that

 {{{
 // 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 );
     }
 }}}

 Is somehow different from the other version published in
 [https://github.com/WordPress/wordpress-develop/pull/8418 8418] patch?
 {{{
 if ( ! $post instanceof WP_Post ) {
         if ( 'ids' === $this->query_vars['fields'] ) {
                 // Post IDs queried.
                 $post = get_post( $post );
         } elseif ( isset( $post->ID ) ) {
                 // Partial object (stdClass) queried.
                 $post = get_post( $post->ID );
         }
 }
 }}}

 From what I found over my previous tests, there were only 3 options:
 1. WP_Post on `all`
 2. A numeric ID, for `ids`
 3. The stdClass for `id=>parent`.

 Anyway, I think that the same in a way or another way, the improvement
 here is just to check for WP_Post to avoid priming cache in just that
 scenario.

 Again, using the same implementation as the patch just before this one,
 the results are barely identical and excluding the `array_reduce` from the
 `ids` doesn't seem to make a difference with such test battery.

 ||= Fields     =||= 6.7 Time    =||= 6.7 Queries =||= 8495 Patch Time
 =||= 8495 Patch Queries =||=  This Comment Patch time  =||= This Comment
 Patch Queries =||
 || all        || 3.2470240592956543 ||         4    || 3.2879478931427 ||
 4    || 3.2534329891204834 ||       4        ||
 || ids        || 3.8917858600616455 ||       5      || 3.8529629707336426
 ||        5       || 3.8428380489349365  ||        5       ||
 || id, parent || 1.0311799049377441  ||      1       || 3.907115936279297
 ||         5      || 3.9453020095825195 ||        5       ||


 This is the function with the `WP_Post` addition

 {{{#!php
 <?php
 public function the_post() {
     global $post;

     if ( ! $this->in_the_loop ) {
         if ( $this->posts && $this->posts[0] instanceof WP_Post ) {
             $post_objects = $this->posts;
         } else {
             // 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 ( is_object( $post ) && isset( $post->ID ) ) {
                         // Query for object, either partial WP_Post or
 stdClass
                         $carry[] = $post->ID;
                     }

                     return $carry;
                 },
                 array()
             );
             if ( $post_ids ) {
                 _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 );
         }
         update_post_author_caches( $post_objects );
     }

     $this->in_the_loop = true;
     $this->before_loop = false;

     if ( -1 === $this->current_post ) { // Loop has just started
         /**
          * Fires once the loop is started.
          *
          * @since 2.0.0
          *
          * @param WP_Query $query The WP_Query instance (passed by
 reference).
          */
         do_action_ref_array( 'loop_start', array( &$this ) );
     }

     $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 );
     }

     // Set up the global post object for the loop
     $this->setup_postdata( $post );
 }
 }}}

 Both versions pass the query unit-tests anyway, so given that both the
 original version with the conditional for `WP_Post` and the last in
 [https://github.com/WordPress/wordpress-develop/pull/8495 8495] seem to be
 identical in performance, functionality and correctness, just choose
 whatever you prefer.

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/56992#comment:45>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list