How to use WP_query(), query_posts() and pre_get_posts in WordPress Programming

How to use WP_query(), query_posts() and pre_get_posts in WordPress Programming

There are legitimate scenarios for using query_posts($query), for example:

You want to display a list of posts or custom-post-type posts on a page (using a page template)

You want to make pagination of those posts work

Now why would you want to display it on a page instead of using an archive template?

It’s more intuitive for an administrator (your customer?) – they can see the page in the ‘Pages’

It’s better for adding it to menus (without the page, they’d have to add the url directly)

If you want to display additional content (text, post thumbnail, or any custom meta content) on the template, you can easily get it from the page (and it all makes more sense for the customer too). See if you used an archive template, you’d either need to hardcode the additional content or use for example theme/plugin options (which makes it less intuitive for the customer)

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.

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 use query_posts() – use pre_get_posts instead.

Use pre_get_posts to alter your main query. Use a separate WP_Query object (method 2) for secondary loops in the template pages.
If you want to alter the query of the main loop, use pre_get_posts.

To modify main loop

don’t use query_posts()
use

pre_get_posts filter with $query->is_main_query()

check
alternately use request filter (a little too rough so above is better)
To run secondary loop
Use new WP_Query or get_posts() which are pretty much interchangeable (latter is thin wrapper for former).


Discover more from mycodetips

Subscribe to get the latest posts sent to your email.

Discover more from mycodetips

Subscribe now to keep reading and get access to the full archive.

Continue reading

Scroll to Top