Seems like half the tutorials in the Codex use wp_reset_postdata()
and half use wp_reset_query()
. What’s the deal? Maybe Use both of them? What about rewind_posts()
? I am asking for an answer based on facts, not on opinions.
1 Answer
wp_reset_postdata()
resets the value of the global $post
variable to the post
property of the main query, which will be whatever post the main query was last on. You would do this if you had used setup_postdata()
or $query->the_post()
on a custom query. Both of these replace the global $post
variable so that functions like the_title()
get the correct title for the current post in a loop.
wp_reset_query()
resets the main query back to whatever it was when originally loaded. The only reason this will happen that I’m aware of is if you have used query_posts()
to modify it. You shouldn’t be doing this in any case. This function also calls wp_reset_postdata()
internally, so will have the same effect.
rewind_posts()
sets the current post in the main query to the first post. Since have_posts()
calls rewind_posts()
internally once you go past the last post, I’m not sure when you’d ever need to use this. Probably only if you ever needed to go back to the beginning of the loop before it has ended.
So basically you should use wp_reset_postdata()
whenever you do either of the following:
A secondary query:
$my_query = new WP_Query( $args );
while ( $my_query->have_posts() ) : $my_query->the_post();
the_title();
endwhile;
wp_reset_postdata();
Looping over get_posts()
results:
global $post;
$my_posts = get_posts( $args );
foreach ( $my_posts as $post ) : setup_postdata( $post );
the_title();
endforeach;
wp_reset_postdata();
Or getting a single post and using template tags:
global $post;
$post = get_post( $id );
setup_postdata( $post );
the_title();
wp_reset_postdata();
And you’d use rewind_posts()
if you ever needed to go to the beginning of the loop. This example’s weird, but I couldn’t think of a better one. It’s basically if you wanted to show the first 3 posts of the loop, then go to the beginning and show all of them:
global $wp_query;
$started_over = false;
while ( have_posts() ) : the_post();
the_title();
if ( ! $started_over && $wp_query->current_post == 2 ) {
$started_over = true;
rewind_posts();
}
endwhile;
And you should basically never need wp_reset_query();