If I'm making additional loops anywhere on a page—in the sidebar, in a footer, any kind of "related posts", etc—I want to be using
WP_Query()
. I can use that repeatedly on a single page without any harm. (right?).What I don't know for sure
- When do I use @nacin's
pre_get_posts
vs.WP_Query
? Should I usepre_get_posts
for everything now? - When I want to modify the loop in a template page — lets say I want to modify a taxonomy archive page — do I remove the
if have_posts : while have_posts : the_post
part and write my ownWP_Query
? Or do I modify the output usingpre_get_posts
in my functions.php file?
tl;dr
The tl;dr rules I'd like to draw from this are:
- Never use
query_posts
anymore - When running multiple queries on a single page, use
WP_Query
- When modifying a loop, do this ________.
Thanks for any wisdom
Terry
ps: I have seen and read: When should you use WP_Query vs query_posts() vs get_posts()? Which adds another dimension —
get_posts
. But doesn't deal with pre_get_posts
at all.Answer:-
You are right to say:
Never usequery_posts
anymore
pre_get_posts
pre_get_posts
is a filter, for altering any query. It is most often used to alter only the 'main query':add_action('pre_get_posts','wpse50761_alter_query');
function wpse50761_alter_query($query){
if( $query->is_main_query() ){
//Do something to main query
}
}
(I would also check that
is_admin()
returns false - though this may be redundant.). The main query appears in your templates as:if( have_posts() ):
while( have_posts() ): the_post();
//The loop
endwhile;
endif;
If you ever feel the need to edit this loop - use
pre_get_posts
. i.e. If you are tempted to usequery_posts()
- use pre_get_posts
instead.WP_Query
The main query is an important instance of a
WP_Query object
. WordPress uses it to decide which template to use, for example, and any arguments passed into the url (e.g. pagination) are all channelled into that instance of the WP_Query
object.For secondary loops (e.g. in side-bars, or 'related posts' lists) you'll want to create your own separate instance of the
WP_Query
object. E.g.$my_secondary_loop = new WP_Query(...);
if( $my_secondary_loop->have_posts() ):
while( $my_secondary_loop->have_posts() ): $my_secondary_loop->the_post();
//The secondary loop
endwhile;
endif;
wp_reset_postdata();
Notice
wp_reset_postdata();
- this is because the secondary loop will override the global$post
variable which identifies the 'current post'. This essentially resets that to the $post
we are on.get_posts()
This is essentially a wrapper for a separate instance of a
WP_Query
object. This returns an array of post objects. The methods used in the loop above are no longer available to you. This isn't a 'Loop', simply an array of post object.<ul>
<?php
global $post;
$args = array( 'numberposts' => 5, 'offset'=> 1, 'category' => 1 );
$myposts = get_posts( $args );
foreach( $myposts as $post ) : setup_postdata($post); ?>
<li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php endforeach; wp_reset_postdata(); ?>
</ul>
0 comments:
Post a Comment