[wp-trac] [WordPress Trac] #20904: WP_Query instances getting entangled with $wp_query global

WordPress Trac wp-trac at lists.automattic.com
Mon Jun 11 11:55:39 UTC 2012


#20904: WP_Query instances getting entangled with $wp_query global
--------------------------+-----------------------------
 Reporter:  boonebgorges  |      Owner:
     Type:  defect (bug)  |     Status:  new
 Priority:  normal        |  Milestone:  Awaiting Review
Component:  Query         |    Version:
 Severity:  normal        |   Keywords:  has-patch
--------------------------+-----------------------------
 `WP_Query::the_post()` fires `setup_postdata()`, which then uses
 `get_query_var()`. `get_query_var()`, in turn, calls the `get()` method on
 the `$wp_query` global object. In this way, WP_Query instances are not
 truly insulated from each other - they all are tied up with `$wp_query` in
 a way that seems unnecessary, and causes fatal errors in some cases.

 In normal use, you would never really notice the issue, because after the
 `'init'` action, the following offending line in `setup_postdata()` will
 return the 'page' query var from `$wp_query`:

 {{{
 $page = get_query_var('page');
 }}}

 And, since secondary `WP_Query` instances don't paginate in the same way
 as the primary query, the 'page' property on those instances doesn't
 matter much. So, while the value of `$page` is not strictly speaking
 correct in these cases (it comes from the wrong object), it generally
 fails silently.

 However, if you instantiate a WP_Query object before 'init', you get a
 fatal error, because `$wp_query->get()` is an undefined method. Here's a
 simple mu-plugin that will demonstrate the problem:

 {{{
 function bbg_create_early_wp_query_object() {
         $q = new WP_Query( array(
                 'post_type' => 'post'
         ) );

         if ( $q->have_posts() ) {
                 while ( $q->have_posts() ) {
                         $q->the_post();
                 }
         }
 }
 add_action( 'plugins_loaded', 'bbg_create_early_wp_query_object' );
 }}}

 My suggested solution is to move the `setup_postdata()` logic into a
 method of the `WP_Query` class, and then use `$this->get( 'page' )` rather
 than `get_query_var( 'page' )`, to ensure that you're referring to the
 query vars of the correct query object. The old function
 `setup_postdata()` then becomes a wrapper for
 `$wp_query->setup_postdata()`.

 In addition, I modified the way that the `$more` global is set, so that it
 references the current object as well. This prevents `_doing_it_wrong()`
 errors when firing up a `WP_Query` instance before `'init'`.

-- 
Ticket URL: <http://core.trac.wordpress.org/ticket/20904>
WordPress Trac <http://core.trac.wordpress.org/>
WordPress blogging software


More information about the wp-trac mailing list