DiggingIntoWordPress

by Chris Coyier & Jeff Starr

3 Ways to Reset the WordPress Loop

Posted by on

WordPress does an excellent job of keeping track of what’s happening with the loop, but once you start customizing parameters and setting up multiple loops, it’s a good idea to explicitly reset them using one of three WordPress template tags. In this DiW post, we’ll explore these techniques to get a better understanding of when and how to use them in your WordPress themes.

wp_reset_postdata()

First up we have wp_reset_postdata, which restores the global $post variable to the current post in the main query. This is useful when using WP_Query to customize loops or create multiple loops on the same page. It looks like this:

<?php wp_reset_postdata(); ?>

This tag is nice and simple – it accepts no parameters and returns no values. It simply resets the post data after a custom query. So for example, let’s say we have a custom WP_Query loop in our theme’s header.php file, something like this:

$random_post = new WP_query(); 
$random_post->query('cat=3&showposts=1&orderby=rand'); 
while ($random_post->have_posts()) : $random_post->the_post(); 
<a href="<?php the_permalink() ?>" title="<?php the_title(); ?>">
	<img src="<?php echo get_post_meta($random_post->ID, 'featured', true); ?>">
</a>
endwhile;

This would display a random post in the header, but it will also change the main query object for any other loops on the page. Without the original query data available, the main posts loop contained in, say, index.php may produce unexpected results. Fortunately, we can use wp_reset_postdata to restore the query object to its original state.

To use wp_reset_postdata, just place after your custom loop(s). Here is our previous example with wp_reset_postdata to reset the loop:

$random_post = new WP_query(); 
$random_post->query('cat=3&showposts=1&orderby=rand'); 
while ($random_post->have_posts()) : $random_post->the_post(); 
<a href="<?php the_permalink() ?>" title="<?php the_title(); ?>">
	<img src="<?php echo get_post_meta($random_post->ID, 'featured', true); ?>">
</a>
endwhile;
wp_reset_postdata();

When to use: best used after custom or multiple loops created with WP_Query.

wp_reset_query()

Next up we have the wp_reset_query function, which resets the query used with custom loops. It’s a simple function that accepts no parameters and returns no values. It looks like this:

<?php wp_reset_query(); ?>

Specifically, this function was created to prevent issues with query_posts, as indicated for the function in the wp-includes/query.php file:

/**
 * Destroy the previous query and set up a new query.
 *
 * This should be used after {@link query_posts()} and before another {@link
 * query_posts()}. This will remove obscure bugs that occur when the previous
 * wp_query object is not destroyed properly before another is set up.
 *
 * @since 2.3.0
 * @uses $wp_query
 */

Looking at the wp_reset_query function in query.php, we see that it uses the adjacent wp_reset_postdata function to restore the global $post variable to the current post in the main query:

// destroy and reset the query
function wp_reset_query() {
	unset($GLOBALS['wp_query']);
	$GLOBALS['wp_query'] =& $GLOBALS['wp_the_query'];
	wp_reset_postdata(); // <-- RESET QUERY
}

// restore the query
function wp_reset_postdata() {
	global $wp_query;
	if ( !empty($wp_query->post) ) {
		$GLOBALS['post'] = $wp_query->post;
		setup_postdata($wp_query->post);
	}
}

So both wp_reset_query() and wp_reset_postdata() reset the query object by restoring the global $post variable, but wp_reset_query takes it a step further and actually destroys the previous query before doing so. This is important when using query_posts(), as seen in the following example:

<?php query_posts('posts_per_page=3');
if (have_posts()) : while (have_posts()) : the_post(); ?>

<h1><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h1>

<?php endwhile; endif; ?>
<?php wp_reset_query(); ?>

When to use: best used after a query_posts loop to reset things after a custom query.

rewind_posts()

Last but not least, we have the rewind_posts function, which basically does what it says: rewinds the loop so you can re-use the same query. The function accepts no parameters, returns no values, and looks like this when used in your theme files:

<?php rewind_posts(); ?>

So to understand when to use rewind_posts(), let’s say we want to use the same query in two different locations on the page. We want to display post titles in the first loop and post content in the second loop. To re-use the same posts, we include rewind_posts after the first loop, like so:

if (have_posts()) : while (have_posts()) : the_post(); ?>
<h1><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h1>
<?php endwhile; endif; ?>

<?php rewind_posts(); ?>

<?php while (have_posts()) : the_post(); ?>
<?php the_content(); ?>
<?php endwhile; ?>

So, while wp_reset_query and wp_reset_postdata reset the entire query object, rewind_posts simply resets the post count, as seen for the function in the wp-includes/query.php file:

// rewind the posts and reset post index
function rewind_posts() {
	$this->current_post = -1;
	if ( $this->post_count > 0 ) {
		$this->post = $this->posts[0];
	}
}

When to use: best for re-using the same query on the same page.

5-second summary

Quick summary for future reference:

  • wp_reset_postdata() -> best used after custom or multiple loops created with WP_Query
  • wp_reset_query() -> best used after a query_posts loop to reset a custom query
  • rewind_posts() -> best for re-using the same query on the same page

I hope this is a useful round-up of when & how to reset/rewind the WordPress loop. Note that the WP Codex information on these functions is kinda thin, so feel free to share any tips or examples in the comments.

11 Responses

  1. Whooaaaa….

    It would be better if you can make a nice little table to explain which method works best with what conditions. That would save me a lot of time.

  2. Great article guys, thanks for the information.

  3. Hi, how about the “$wpdb -> get_results()”? Thank you!

  4. January Corsilles September 14, 2011

    You actually make it seem so easy with your presentation but I find this topic to be actually something that I think I would never understand. It seems too complex and extremely broad for me. I’m looking forward for your next post, I’ll try to get the hang of it!

  5. What I find strange tho is that I’m able to filter the first loop-> then rewind-> then filter differently instead of filtering some more.

    I’d expect problems cause both categories are primairy cats, but it seems to work just fine.

    <?php query_posts('category_name=name1&posts_per_page=1'); ?>
    <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
    <?php the_content(); ?>
    <?php endwhile; else: ?>
    sorry no posts...
    <?php endif; ?>

    <?php rewind_posts(); ?>
    <?php query_posts('category_name=name2&posts_per_page=6'); ?>
    <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
    and so on..

    • Hmm, that is interesting.. does it behave the same way when including the same category in both loops, maybe something like this:

      query_posts('cat=1,2&posts_per_page=1');
      ...
      <?php rewind_posts(); ?>
      ...
      query_posts('cat=1,3&posts_per_page=6');
      ...

      My guess is that this won’t work, but then again I haven’t had my coffee yet.

      • I would hazard a guess that this would work perfectly if using two calls to WP_Query() instead.

        Using query_posts() is intended to modify the default query, which should only be queried once. If the template needs two separate queries, don’t rely on multiple calls to query_posts() to return those two separate queries; use WP_Query() instead.

  6. awesome.. i learned rewind_posts() function from this article..

  7. wow, great staff. Thank you very much for the great tutorial. I’ve had some problems with the loop, but you’ve solved them!

  8. Stumbled into this, and will comment. I usually go with the first or second one. This may sound like a dumb question but why would you need to run the same query twice on a page?

    • For example, you may need to loop through the posts to determine if a particular shortcode is used, so that you can enqueue a script or stylesheet.

Comments are closed. Contact us with any critical information. Thank you!

Code is poetry