it’s unclear when to use one or the other, or if they must be used at
all
-
If you’ve modified the global
$wp_query
variable (e.g. usingquery_posts()
which should NOT actually be used), then usewp_reset_query()
to restore the variable back to the main query, i.e. so that the variable references or points to the main query again, and for example when you callhave_posts()
, it would check against the main query (whether it contains any posts) and not some other/custom query.// This (should NOT be done and it) modifies the $wp_query global. query_posts( 'posts_per_page=2' ); while ( have_posts() ) { the_post(); the_title( '<h3>', '</h3>' ); } // This restores the $wp_query global back to the main query. wp_reset_query();
-
If you’ve modified the global
$post
variable (e.g. usingsetup_postdata()
or by calling thethe_post()
method in a secondary/customWP_Query
instance), then usewp_reset_postdata()
to restore the variable back to the current post in the main query, so that for example callingthe_title()
would display the title of the second post in the main query and not the last post in a secondary query.// Case 1: Calling the the_post() method in a custom WP_Query instance. $query = new WP_Query( 'posts_per_page=2' ); while ( $query->have_posts() ) { // This modifies the $post global. $query->the_post(); the_title( '<h3>', '</h3>' ); } // Restore the $post global back to the current post in the main query. wp_reset_postdata(); // Case 2: Using setup_postdata(). global $post; $posts = get_posts( 'posts_per_page=2' ); foreach ( $posts as $post ) { // This modifies the $post global. setup_postdata( $post ); the_title( '<h3>', '</h3>' ); } // Restore the $post global back to the current post in the main query. wp_reset_postdata();
So in the two examples above, we only called
wp_reset_postdata()
and there’s no need to callwp_reset_query()
because neither of the two queries modified the main query (or the global$wp_query
variable).
Therefore, if the $wp_query
global is not modified, then no need to call wp_reset_query()
, and if the $post
global is not modified, then no need to call wp_reset_postdata()
. I.e. Call just one of them.
Additional Notes
-
query_posts()
will change the main query and is not recommended. Only use if absolutely necessary. Creating a new instance ofWP_Query
orget_posts()
is preferred for secondary loops. If you would like to modify the main query, use thepre_get_posts
action. -
In a
pre_get_posts
hook, you can use theis_main_query()
method in the passed query object, to check whether the current query is the main query. Same goes with hooks likeposts_orderby
which passes (if requested) the query object to the hook callbacks. -
The hooks in
WP_Query
also fires on the admin side (wp-admin
), so you can useis_admin()
to avoid changing the main query on the admin, unless of course if that is something you intended to do.
And I’m not exactly sure the main points in your question (or the exact kind of answer that you’re looking for), but I hope this answer helps. 🙂