[wp-trac] [WordPress Trac] #9256: clean up the global variables when moving out of the loop

WordPress Trac wp-trac at lists.automattic.com
Tue Mar 2 10:42:51 UTC 2010


#9256: clean up the global variables when moving out of the loop
-------------------------------------+--------------------------------------
 Reporter:  aldolat                  |        Owner:  anonymous     
     Type:  enhancement              |       Status:  reopened      
 Priority:  normal                   |    Milestone:  Future Release
Component:  Query                    |      Version:  2.7.1         
 Severity:  normal                   |   Resolution:                
 Keywords:  has-patch needs-testing  |  
-------------------------------------+--------------------------------------

Comment(by mdgl):

 I think the problem here is in "setup_postdata()" (query.php) and its
 handling of global variables.

 The function "setup_postdata()" sets the global variable "$page" based on
 the instance variables of the global query object, i.e. "$page =
 get_query_var('page')".

 Of course if you have done a separate query (e.g. with "get_posts()",
 "get_children()" or a new "WP_Query" object) and are trying to make use of
 the template functions by calling "setup_postdata()", this is incorrect as
 the value of "$page" should be related to your separate query, not the
 enclosing loop.

 The problem is further compounded because "setup_postdata()" only
 overwrites the first entry in the global "$pages[]" array if your separate
 query has only a single page. Hence, the other array entries still contain
 data from the main page and can be inadvertently accessed by function
 "get_the_content()" using the incorrect value of "$page".

 I believe a workaround is to code as follows:

 {{{
 $myposts = &get_posts(...) /* Or new WP_Query or whatever. */
 global $post, $page;
 $mysavedpost = $post;
 foreach ($myposts as $post) {
    setup_postdata($post); $page = 1;

    the_title(); the_content(); /* And so on. */

 }
 $post = $mysavedpost; setup_postdata($post);
 }}}

 With the increased use of widgets and complex page templates, such "nested
 loops" can only become more and more common.  Although we're still using
 global variables in the loop, and "setup_postdata()" still needs to be
 fixed, a better solution here would be to offer full support for a
 "save/restore" paradigm for handling nested loops, for example:

 {{{
 $myposts = new WP_Query(...);
 $myposts->save_loop_state(); /* Copies all required globals into new query
 object. */
 while ($myposts->have_posts()) :
    $myposts->the_post(); /* Stomps on global variables. */
    ... /* Use global variables through template tags. */
 endwhile;
 $myposts->restore_loop_state(); /* Restores all required globals from new
 query object. */
 }}}

 With a bit of thought, this could perhaps even be made automatic and
 transparent within the query "have_posts()" and "the_post()" methods,
 although you would still have to have a method for coping with early exit
 from the loop.

 Presently, we seem to have too much forcing of one loop to run after
 another, use of "wp_reset_query()" and so on, which is all a bit messy
 (IMHO).

-- 
Ticket URL: <http://core.trac.wordpress.org/ticket/9256#comment:11>
WordPress Trac <http://core.trac.wordpress.org/>
WordPress blogging software


More information about the wp-trac mailing list