Mastering WP_Query: An Introduction

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:

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() and get_pages() are very similar, with the main difference being obvious from their names. These template tags actually use the WP_Query class, so they are another way of doing the same thing, but add an extra step because they call the WP_Query class instead of you doing it directly. You can only use them to query either posts or pages, while WP_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, use pre_get_posts instead, and if you want to create a completely new query, use WP_Query.

The diagram below, released by Andrey “Rarst” Savchenko under Creative Commons license, makes some sense of this:

Make Sense of WP_Query Functions

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 use pre_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.


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.



Related Articles