[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