By default, WordPress will run a query on each page that your site displays, the nature of which will be determined by the type of page being viewed. So if a static page is being viewed, WordPress runs a query to display the page with the relevant ID, while if an archive page is being viewed, the query will retrieve all posts in that archive.
But sometimes you want to do things a bit differently. Either in your page's main content or elsewhere on the page (such as in the sidebar or footer), you might want to display some specific content which isn't output by the standard query.
The great news is that WordPress makes that possible with the WP_Query
class. This class provides you with a large number of parameters you can use to define what content you want to output (which needn't be limited to posts) and then write a loop which will show the content exactly as you want to.
In this nineteen-part series on Mastering WP_Query
, Baris Unver and I will take you through the ins and outs of WP_Query
so that once you've completed the series, you'll be able to use it in a variety of scenarios and fine tune the way WordPress queries the data in your site's database.
In this introduction I'll cover the following:
- What is
WP_Query
? - Why use
WP_Query
? - Potential problems / what to be aware of.
What Is WP_Query?
WP_Query
is a class provided by WordPress. The fact that it's a class means that by using it you can quickly access the variables, checks and functions which have been coded into that class in WordPress core, without having to worry about writing all that code yourself. This makes your code more efficient and reliable.
If you want to understand exactly how WP_Query
works under the hood, you can see its code in the includes/query.php
file.
WP_Query
consists of four main elements:
- the arguments for the query, using parameters which will be covered in detail in this series
- the query itself
- the loop, which will output post content, titles or whatever you want to display
- finishing off: closing if and while tags and resetting post data
In practice this will look something like the following:
<?php $args = array( // Arguments for your query. ); // Custom query. $query = new WP_Query( $args ); // Check that we have query results. if ( $query->have_posts() ) { // Start looping over the query results. while ( $query->have_posts() ) { $query->the_post(); // Contents of the queried post results go here. } } // Restore original post data. wp_reset_postdata(); ?>
You could define your arguments when writing the query itself, but I prefer to define those first, as it keeps things neat.
Resetting Post Data
In the example above I've added wp_reset_postdata()
after each query. This is important because it resets the query back to the main query being run on that page.
For example, if you're using WP_Query
to run a query in the sidebar, using wp_reset_postdata()
effectively tells WordPress that we're still on whatever page is being viewed and that it should work with the default query for that page.
If you don't do this, any other queries being run on the page (including the default query) might break, and any conditional tags checking for what kind of page is being viewed won't work.
Why Use WP_Query?
If you haven't used the WP_Query
class before, you may be wondering why you should start. Here I'm going to focus on two aspects of this: why use WP_Query
over other methods of writing custom queries, and scenarios where you might want to use WP_Query
.
Why Use WP_Query Over Other Methods?
WP_Query isn't the only method for creating a custom query. There are four more:
pre_get_posts
get_posts()
get_pages()
-
query_posts()
(which you should avoid, as I'll explain)
I'm not going to go into a lot of detail as to how each of these work, but it's helpful to know when they're used:
-
pre_get_posts
is a hook which modifies the main query. You can use it with a conditional tag to check if a certain type of page is being viewed (for example the home page) and then use it to amend the query that's run (for example to remove the most recent three posts, if you're displaying them elsewhere on the page). It's a very efficient way of modifying the main query and should be your first port of call if that's what you want to do. However you can't use it to create a completely new query. -
get_posts()
andget_pages()
are very similar, with the main difference being obvious from their names. These template tags actually use theWP_Query
class, so they are another way of doing the same thing, but add an extra step because they call theWP_Query
class instead of you doing it directly. You can only use them to query either posts or pages, whileWP_Query
itself is more powerful and lets you query almost anything held in your database. -
query_posts()
modifies the main query but shouldn't be used in plugins or themes. This is because it throws out the main query and starts all over again, replacing the main query with a new query. It is also prone to errors, particularly with pagination, and is inefficient and will affect your page load times. If you need to modify the main query, usepre_get_posts
instead, and if you want to create a completely new query, useWP_Query
.
The diagram below, released by Andrey “Rarst” Savchenko under Creative Commons license, makes some sense of this:
When You Might Use WP_Query
There are many scenarios when WP_Query
will come in useful, and I can't cover them all here, but here's an overview:
- To add a list of related posts under the current post—for example a list of all posts in the same category.
- To create two loops on the same page: for example an FAQ page with the question titles at the top and the content beneath.
- To create a custom list of recent posts in the sidebar or footer of your site, when the Recent Posts widget doesn't do what you need (or you'd rather code it yourself).
- To create custom queries for taxonomies, using more than one taxonomy to define what's displayed.
- To query post types which aren't output by the default query, such as attachments.
- To create custom pages with a number of queries for different content types, as I've done in this example site for a client.
Some Caveats
The WP_Query
class is great. I create a lot of sites needing custom queries, so I use it frequently. But it doesn't come without its downsides. Here are some things you should be aware of:
- If all you want to do is change the way posts are being displayed for a particular content type or archive, don't use
WP_Query
. Instead, simply create a template file for that archive or content type, and modify the loop in that template file. - If you want to display a few more or less posts than would normally be shown on an archive page (for example not showing a particular category), don't use
WP_Query
to create a whole new query. Instead usepre_get_posts
to modify the main query, along with a conditional tag to single out where exactly you want to do it. - Beware of running too many queries on a page. You could theoretically create a page with hundreds of custom queries, but just think of the server load. If you need more than four or five queries on a page, you might want to consider creating extra pages.
Summary
The WP_Query
class is a powerful and extremely useful tool for creating custom queries and making your WordPress site behave exactly as you want it to. As we've seen, there are times when you would use other methods to create custom queries, but it does have a wide range of uses.
In the rest of this series, we'll take you through the details of how to use WP_Query
and get the most from it.
Comments