{"id":169520,"date":"2017-12-14T13:00:17","date_gmt":"2017-12-14T13:00:17","guid":{"rendered":"https:\/\/premium.wpmudev.org\/blog\/?p=169520"},"modified":"2017-12-07T19:09:43","modified_gmt":"2017-12-07T19:09:43","slug":"how-to-use-one-query-to-run-multiple-loops","status":"publish","type":"post","link":"https:\/\/wpmudev.com\/blog\/how-to-use-one-query-to-run-multiple-loops\/","title":{"rendered":"How to Use One Query to Run Multiple Loops"},"content":{"rendered":"<p>I&#8217;ve written a few posts here on the blog about the WP_Query\u00a0class and how to use it to create multiple queries and multiple loops.<\/p>\n<p>I&#8217;m a big fan of <code><a href=\"https:\/\/codex.wordpress.org\/Class_Reference\/WP_Query\" target=\"_blank\">WP_Query<\/a><\/code>, and often use it on client sites and my own site to create advanced and custom queries.<\/p>\n<p>However, it does have its downsides if you overdo things. One reader rightly commented on my recent post on <a href=\"https:\/\/wpmudev.com\/blog\/two-versions-wordpress-loop\/\" target=\"_blank\">using the loop to style your first post differently<\/a>, that the technique I demonstrated could be made more efficient.<\/p>\n<p>So in this post, I&#8217;m going to show you how to use <code>WP_Query<\/code> to create multiple loops but in the most efficient way possible &#8211; and that is by running just one query but then using it to create multiple loops.<\/p>\n<p>The benefit of doing this is that you&#8217;re only hitting up the database once. You can then use all the data that <code>WP_Query<\/code> fetches for you to run as many loops as you need.<\/p>\n<p>So let&#8217;s dive in and see how it works.<\/p>\n<h3>What We&#8217;ll Be Doing<\/h3>\n<p>In this post, I&#8217;m going to create a section at the top of my site&#8217;s home page that displays recent and specific content from a number of post types. Specifically, it&#8217;s going to display:<\/p>\n<ul>\n<li>My latest post from a custom post type<\/li>\n<li>Two posts from the <em>post<\/em> post type: one from each of two categories.<\/li>\n<li>A specific page.<\/li>\n<\/ul>\n<p>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 <code>WP_Query<\/code>, each of which returns one post. But instead I&#8217;m going to run <code>WP_Query<\/code> 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&#8217;ll use a variable called $count and I&#8217;ll increase its value by 1 so I can check on that in the next loop.<\/p>\n<h3>What You&#8217;ll Need<\/h3>\n<p>To follow along with this post, you&#8217;ll need a few things:<\/p>\n<ul>\n<li>A development installation of <a href=\"https:\/\/wordpress.org\/download\/\" target=\"_blank\">WordPress<\/a><\/li>\n<li>A <a href=\"https:\/\/wpmudev.com\/blog\/best-text-editors-wordpress\/\" target=\"_blank\">code editor<\/a><\/li>\n<\/ul>\n<h3>Setting Up The Query<\/h3>\n<p>The first thing to do is run the query. I&#8217;m putting this post in my theme template file for the home page, <em>front-page.php<\/em>. But you could put it anywhere in your theme that you wanted to run multiple loops.<\/p>\n<p><em>Note: If you&#8217;re working with a third party theme, put all this in a child theme, not in the third party theme. If you don&#8217;t know how to set up a child theme, see <a href=\"https:\/\/wpmudev.com\/blog\/how-to-create-wordpress-child-theme\/\" target=\"_blank\">our guide<\/a>.<\/em><\/p>\n<p>Here&#8217;s my query:<\/p>\n<div class=\"gist\" data-gist=\"93772b5f9a86936aebe4d03b530c3d89\" data-gist-file=\"wp_query.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/93772b5f9a86936aebe4d03b530c3d89.js?file=wp_query.php\">Loading gist 93772b5f9a86936aebe4d03b530c3d89<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>That query will fetch posts of three post types: <em>posts<\/em>, <em>pages<\/em>, and my custom post type <em>books<\/em>.<\/p>\n<p>So now we&#8217;ve fetched the posts from the database, we need to start setting up the code to output them.<\/p>\n<h3>Setting up the Output<\/h3>\n<p>After your query and inside the braces, add this:<\/p>\n<div class=\"gist\" data-gist=\"93772b5f9a86936aebe4d03b530c3d89\" data-gist-file=\"opening_code.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/93772b5f9a86936aebe4d03b530c3d89.js?file=opening_code.php\">Loading gist 93772b5f9a86936aebe4d03b530c3d89<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>This creates a <code>section<\/code> element which will contain all of our posts. It also defines a variable called $count and sets that to zero. We&#8217;ll make that go up by one after each loop.<\/p>\n<h3>Running the First Loop<\/h3>\n<p>My first loop will output my custom post type. So within the loop, we&#8217;ll include a conditional tag that will check for that post type. It&#8217;ll also check that the value of $count is 0 and after running, it&#8217;ll increase that value by 1 to stop the loop running again.<\/p>\n<p>Here&#8217;s the code:<\/p>\n<div class=\"gist\" data-gist=\"93772b5f9a86936aebe4d03b530c3d89\" data-gist-file=\"first_loop.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/93772b5f9a86936aebe4d03b530c3d89.js?file=first_loop.php\">Loading gist 93772b5f9a86936aebe4d03b530c3d89<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>Note that this includes the\u00a0<code>get_post_type()<\/code> function to identify what the post type is, and only run the loop if that&#8217;s <em>book<\/em> and the value of count is 0. Then at the end,\u00a0<code>$count++<\/code> will increase the value of the $count variable by 1.<\/p>\n<p>The final element of this loop is <code>rewind_posts()<\/code>. Don&#8217;t leave this out, or you&#8217;ll find that your loops don&#8217;t run correctly as they&#8217;ll skip any posts of your other post types that were published after this &#8216;book&#8217; post.<\/p>\n<h3>Running the Second Loop<\/h3>\n<p>Now for your second loop. It&#8217;s similar to the first one: it checks the value of $count and the post type, but also checks for a category.<\/p>\n<div class=\"gist\" data-gist=\"93772b5f9a86936aebe4d03b530c3d89\" data-gist-file=\"second_loop.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/93772b5f9a86936aebe4d03b530c3d89.js?file=second_loop.php\">Loading gist 93772b5f9a86936aebe4d03b530c3d89<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>Note that we&#8217;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 &#8216;book&#8217; post.<\/p>\n<h3>Running the Third Loop<\/h3>\n<p>The third loop is very similar to the second: it&#8217;s checking for a post in the &#8216;news&#8217; category but not in the &#8216;wordpress&#8217; category as we&#8217;ve already output the latest post in that category. If I didn&#8217;t include that check, then the same post might be displayed twice.<\/p>\n<div class=\"gist\" data-gist=\"93772b5f9a86936aebe4d03b530c3d89\" data-gist-file=\"third_loop.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/93772b5f9a86936aebe4d03b530c3d89.js?file=third_loop.php\">Loading gist 93772b5f9a86936aebe4d03b530c3d89<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<h3>Running the Fourth Loop<\/h3>\n<p>The fourth and final loop outputs a page: for me this is my newsletter signup page.<\/p>\n<p>Here&#8217;s the code:<\/p>\n<div class=\"gist\" data-gist=\"93772b5f9a86936aebe4d03b530c3d89\" data-gist-file=\"fourth_loop.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/93772b5f9a86936aebe4d03b530c3d89.js?file=fourth_loop.php\">Loading gist 93772b5f9a86936aebe4d03b530c3d89<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>Note that as well as checking for the post type I&#8217;m also checking for the slug with the <code>post_name<\/code> value.<\/p>\n<p>After the fourth loop, we need to close the section element and then we&#8217;re done.<\/p>\n<h3>The Content of the Loop &#8211; Using a Template Part<\/h3>\n<p>You may have noticed that in each loop, I have this line:<\/p>\n<div class=\"gist\" data-gist=\"93772b5f9a86936aebe4d03b530c3d89\" data-gist-file=\"include_template_file.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/93772b5f9a86936aebe4d03b530c3d89.js?file=include_template_file.php\">Loading gist 93772b5f9a86936aebe4d03b530c3d89<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>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.<\/p>\n<p>You might be more familiar with using the <a href=\"https:\/\/developer.wordpress.org\/reference\/functions\/get_template_part\/\" target=\"_blank\"><code>get_template_part()<\/code><\/a> function to call the loop. The reason I&#8217;ve used <code>include( locate_template() )<\/code> instead, is that it&#8217;s possible to pass a variable back and forth to the template part using that function, but not with <code>get_template_part()<\/code>. So you&#8217;ll need to use the function that I&#8217;ve used.<\/p>\n<p>Here&#8217;s the content of my template part:<\/p>\n<div class=\"gist\" data-gist=\"93772b5f9a86936aebe4d03b530c3d89\" data-gist-file=\"template_part.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/93772b5f9a86936aebe4d03b530c3d89.js?file=template_part.php\">Loading gist 93772b5f9a86936aebe4d03b530c3d89<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>Let&#8217;s take a look at some of the more advanced aspects of that code:<\/p>\n<ul>\n<li>I&#8217;m using a variable called <code>$title<\/code> to define the title that will appear above the post in each loop. This isn&#8217;t related to the post itself but to the category or post type. Instead of trying to fetch those dynamically I&#8217;m just assigning a value to that variable depending on what the value of $count is.<\/li>\n<li>For each post. the value of <code>$title<\/code> will be displayed in a <code>h3<\/code> element, followed by the featured image, the title and the excerpt.<\/li>\n<li>Both the featured image and the title act as a link to the post or page.<\/li>\n<\/ul>\n<p>You&#8217;ll need to create your own template part for your loop&#8217;s contents. Tweak it so it works the way you want it to.<\/p>\n<p>Here&#8217;s my list of posts on my home page:<\/p>\n<div  class=\"wpdui-pic-regular  \"> <img loading=\"lazy\" decoding=\"async\" class=\"attachment-600x600 size-600x600\" src=\"https:\/\/wpmudev.com\/blog\/wp-content\/uploads\/2017\/12\/posts-no-styling.png\" alt=\"posts displayed one on top of the other with featured image but no layout styling\" width=\"476\" height=\"600\" \/> <\/div>\n<p>They&#8217;re showing up but they don&#8217;t look so good. Let&#8217;s add some styling.<\/p>\n<h3>Styling Your Posts<\/h3>\n<p>Let&#8217;s add a couple of classes to the article element in each loop, so we can style it. Edit the <code>article<\/code> element in your include file so it looks like this:<\/p>\n<div class=\"gist\" data-gist=\"93772b5f9a86936aebe4d03b530c3d89\" data-gist-file=\"post_class.php\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/93772b5f9a86936aebe4d03b530c3d89.js?file=post_class.php\">Loading gist 93772b5f9a86936aebe4d03b530c3d89<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>Now, add some styling to your theme&#8217;s stylesheet:<\/p>\n<div class=\"gist\" data-gist=\"93772b5f9a86936aebe4d03b530c3d89\" data-gist-file=\"style.css\"><a class=\"loading\" href=\"https:\/\/gist.github.com\/93772b5f9a86936aebe4d03b530c3d89.js?file=style.css\">Loading gist 93772b5f9a86936aebe4d03b530c3d89<\/a><div class=\"gist-consent-notice\" style=\"display:none\"><p>Please <a href=\"javascript:Cookiebot.renew()\">update your cookie preferences<\/a> to enable preference cookies to view this gist.<\/p><\/div><\/div>\n<p>Now save that and refresh your page. Here&#8217;s mine with my grid of posts:<\/p>\n<div  class=\"wpdui-pic-regular  \"> <img loading=\"lazy\" decoding=\"async\" class=\"attachment-600x600 size-600x600\" src=\"https:\/\/wpmudev.com\/blog\/wp-content\/uploads\/2017\/12\/posts-with-styling.png\" alt=\"posts displayed side by side\" width=\"600\" height=\"459\" \/> <\/div>\n<p>I think you&#8217;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.<\/p>\n<h3>Running One Query For Multiple Loops Benefits Your Code and Your Site<\/h3>\n<p>Using this technique, or your own version of it, to run multiple loops while querying the database just once has a number of benefits:<\/p>\n<ul>\n<li>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.<\/li>\n<li>By querying the database just once, you avoid any lag and speed up page load times.<\/li>\n<li>Having a page that loads quickly will improve the user experience and your search engine rankings.<\/li>\n<\/ul>\n<p>What&#8217;s not to like? Try this technique today with your posts, categories and custom post types and see what you can do.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve written a few posts here on the blog about the WP_Query\u00a0class and how to use it to create multiple queries and multiple loops. I&#8217;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 [&hellip;]<\/p>\n","protected":false},"author":347011,"featured_media":169616,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"blog_reading_time":"","wds_primary_category":0,"wds_primary_tutorials_categories":0,"footnotes":""},"categories":[263],"tags":[1044,174,10045],"tutorials_categories":[],"class_list":["post-169520","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-css","tag-php","tag-customization"],"_links":{"self":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/169520","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/users\/347011"}],"replies":[{"embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/comments?post=169520"}],"version-history":[{"count":12,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/169520\/revisions"}],"predecessor-version":[{"id":169617,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/posts\/169520\/revisions\/169617"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/media\/169616"}],"wp:attachment":[{"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/media?parent=169520"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/categories?post=169520"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/tags?post=169520"},{"taxonomy":"tutorials_categories","embeddable":true,"href":"https:\/\/wpmudev.com\/blog\/wp-json\/wp\/v2\/tutorials_categories?post=169520"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}