How to Use One Query to Run Multiple Loops

I’ve written a few posts here on the blog about the WP_Query class and how to use it to create multiple queries and multiple loops.

I’m a big fan of WP_Query, and often use it on client sites and my own site to create advanced and custom queries.

However, it does have its downsides if you overdo things. One reader rightly commented on my recent post on using the loop to style your first post differently, that the technique I demonstrated could be made more efficient.

So in this post, I’m going to show you how to use WP_Query to create multiple loops but in the most efficient way possible – and that is by running just one query but then using it to create multiple loops.

The benefit of doing this is that you’re only hitting up the database once. You can then use all the data that WP_Query fetches for you to run as many loops as you need.

So let’s dive in and see how it works.

What We’ll Be Doing

In this post, I’m going to create a section at the top of my site’s home page that displays recent and specific content from a number of post types. Specifically, it’s going to display:

  • My latest post from a custom post type
  • Two posts from the post post type: one from each of two categories.
  • A specific page.

The obvious way to do this would be to write four (or maybe three if you can just use one for both posts) instances of WP_Query, each of which returns one post. But instead I’m going to run WP_Query once to fetch all of the posts I need, and then run the loop four times to output the required posts. Each time I run the loop, I’ll use a variable called $count and I’ll increase its value by 1 so I can check on that in the next loop.

What You’ll Need

To follow along with this post, you’ll need a few things:

Setting Up The Query

The first thing to do is run the query. I’m putting this post in my theme template file for the home page, front-page.php. But you could put it anywhere in your theme that you wanted to run multiple loops.

Note: If you’re working with a third party theme, put all this in a child theme, not in the third party theme. If you don’t know how to set up a child theme, see our guide.

Here’s my query:

That query will fetch posts of three post types: posts, pages, and my custom post type books.

So now we’ve fetched the posts from the database, we need to start setting up the code to output them.

Setting up the Output

After your query and inside the braces, add this:

This creates a section element which will contain all of our posts. It also defines a variable called $count and sets that to zero. We’ll make that go up by one after each loop.

Running the First Loop

My first loop will output my custom post type. So within the loop, we’ll include a conditional tag that will check for that post type. It’ll also check that the value of $count is 0 and after running, it’ll increase that value by 1 to stop the loop running again.

Here’s the code:

Note that this includes the get_post_type() function to identify what the post type is, and only run the loop if that’s book and the value of count is 0. Then at the end, $count++ will increase the value of the $count variable by 1.

The final element of this loop is rewind_posts(). Don’t leave this out, or you’ll find that your loops don’t run correctly as they’ll skip any posts of your other post types that were published after this ‘book’ post.

Running the Second Loop

Now for your second loop. It’s similar to the first one: it checks the value of $count and the post type, but also checks for a category.

Note that we’re checking that the value of $count is 1 before running this loop, which it will be if the first loop has been run for the ‘book’ post.

Running the Third Loop

The third loop is very similar to the second: it’s checking for a post in the ‘news’ category but not in the ‘wordpress’ category as we’ve already output the latest post in that category. If I didn’t include that check, then the same post might be displayed twice.

Running the Fourth Loop

The fourth and final loop outputs a page: for me this is my newsletter signup page.

Here’s the code:

Note that as well as checking for the post type I’m also checking for the slug with the post_name value.

After the fourth loop, we need to close the section element and then we’re done.

The Content of the Loop – Using a Template Part

You may have noticed that in each loop, I have this line:

This calls the include file with the contents of my loop. Using this file means I only have to write that code once instead of four times.

You might be more familiar with using the get_template_part() function to call the loop. The reason I’ve used include( locate_template() ) instead, is that it’s possible to pass a variable back and forth to the template part using that function, but not with get_template_part(). So you’ll need to use the function that I’ve used.

Here’s the content of my template part:

Let’s take a look at some of the more advanced aspects of that code:

  • I’m using a variable called $title to define the title that will appear above the post in each loop. This isn’t related to the post itself but to the category or post type. Instead of trying to fetch those dynamically I’m just assigning a value to that variable depending on what the value of $count is.
  • For each post. the value of $title will be displayed in a h3 element, followed by the featured image, the title and the excerpt.
  • Both the featured image and the title act as a link to the post or page.

You’ll need to create your own template part for your loop’s contents. Tweak it so it works the way you want it to.

Here’s my list of posts on my home page:

posts displayed one on top of the other with featured image but no layout styling

They’re showing up but they don’t look so good. Let’s add some styling.

Styling Your Posts

Let’s add a couple of classes to the article element in each loop, so we can style it. Edit the article element in your include file so it looks like this:

Now, add some styling to your theme’s stylesheet:

Now save that and refresh your page. Here’s mine with my grid of posts:

I think you’ll agree that looks a lot better than a simple list of posts, and is more powerful than just listing out posts from the blog. It gives me much more flexibility.

Running One Query For Multiple Loops Benefits Your Code and Your Site

Using this technique, or your own version of it, to run multiple loops while querying the database just once has a number of benefits:

  • It means you have just one query to code and keep updated, making your coding more efficient. This is made even more efficient by using the template part.
  • By querying the database just once, you avoid any lag and speed up page load times.
  • Having a page that loads quickly will improve the user experience and your search engine rankings.

What’s not to like? Try this technique today with your posts, categories and custom post types and see what you can do.