How to ensure WordPress template tags work properly when using multiple WordPress Loops

Tuesday, 8th December 2009

There are many occasions when you may want to create multiple WordPress Loops – instructions on how to do this can be found on the WordPress Codex.

If you need to keep the original query, it is suggested you create you second loop by creating a new query object.

<?php $my_query = new WP_Query('category_name=special_cat&posts_per_page=10'); ?>
<?php while ($my_query->have_posts()) : $my_query->the_post(); ?>
   <!-- Do special_cat stuff... -->
<?php endwhile; ?>

This works fine, but if you use more template tags after this loop, they display the content from the last post in the $my_query loop. So, if you want to reference the original loop how should you go about it?

What’s going on?

In the above example the $my_query variable is an instance of the WP_Query object containing the results of the custom query.

The ‘while’ loop iterates through all the results of our query. Each time $my_query->have_posts() is called it checks wether the next post in the loop exists and if it does the loop continues to run.

For each post in the loop the $my_query->the_post() function is called. This populates the global $post variable with the post data which can then be accessed directly through the $post variable or using WordPress template tags like the_title() and the_content();

After the $my_query loop has finished the global $post variable remains populated with the last post from the $my_query loop so any template tags used will use this post’s data, not the data from the post before we started our custom loop.

So what should we do?

Because we created a new query $my_query, the previous query still exists in the main $wp_query variable, so all we have to do is repopulate the $post variable using $wp_query and setup the post data again.

<?php
$post = $wp_query->post;
setup_postdata( $post );
?>

Could this be made more easy?

Not really, but maybe a WordPress template tag to do this should be added to WordPress core – maybe somthing like refresh_post(). This can then be documented in the Codex to provide an ‘official’ way of handling multiple loops.

What do you think?

Leave a Reply