In order to adequately develop a fully functioning WordPress (WP) theme, you need to know WP Query and understand how it works, why it’s necessary, when you need to use it and where it should be placed. WP Query is a class with a host of powerful functions (called template tags in WordPress) that allow you to call up the WP database and have it return the data that you need. Knowing that, you can use WP Query to do things such as display specific posts, categories, images and even use it in conjunction with custom post types to get at the specific data that you need for your WP theme or plugin project.
What You Need to Have and Know
I’m not going to go into too much detail about what programming is, but I will try my best to elaborate on some of the concepts for those who might not be familiar with it. This tutorial will assume that you posess:
- Knowledge of HTML (intermediate)
- A passing understanding of PHP is helpful
- A basic understanding of WordPress’ file structure
- How to set up a bare bones WordPress instance on your localhost (see here for help)
Before you go on with the tutorial, set up a new instance of WordPress on your localhost, you don’t need to install any themes, plugins or special extensions. I am going to use the base TwentyFifteen theme that comes with vanilla WordPress for this tutorial and that should be all that you’ll need too. If you need help installing WordPress on your localhost, head here if you run Windows and here if you run OSX (skillcrush.com).
Because PHP needs to interact on a server level with the database, you must run a local server environment or run a live server environment for any of the demo code in this tutorial to work. I highly recommend setting up a local server environment either using XAMPP or MAMP as working on a live server is much less efficient.
A Crash Course in OOP
WP_Query is a Class that exists within WordPress. It was (like the majority of the WordPress core software) written in PHP. PHP is an Object Oriented Programming language that allows you to write code that interacts with a database. In WordPress’ case, that is typically a MySQL database. This database stores a lot of information for WordPress websites, including user information, all posts, image paths and more.
What’s a Class?
In Object Oriented Programming (typically shortened to OOP), a class can be simply described as a bunch of functions and variables grouped together. A variable is a container for data, a function is code that is written to perform a task and can be reused over and over again. Inside of a Class, Functions are called Methods and Variables are called Properties.
Now, within WP_Query there are a ton of functions that have been pre-written by the WP Developers. These functions are called Template Tags (instead of Methods). Each Template Tag does something specific. For example the get_the_title() template tag will retrieve the title for a post or page.
Many Template Tags (much like Methods) take parameters, which are values that you can feed the Template Tag in order to get specific kinds of information. Most of the time, when you use a WP_Query, you’re looking for more than just one piece of information. Which frequently requires you to put in multiple parameters by loading them up into an array, but we’ll get to that soon.
The final thing we should probably be familiar with is the semicolon that ends all PHP statements. Missing a semicolon can cause all of our code to break so it’s important to watch out for them.
What’s a Query?
A Query, in programming, is the act of asking the database to retrieve and return information to us. This information can be anything from the first names of all our users, to the post titles of all the posts in a specific category. How you write your query and what you ask for will determine what you get back from the database.
In WP’s case, all of its Template Tags were written to query the database for specific pieces of information. And there are a lot of them if you look at the WP Codex for WP_Query: WP Query Documentation (WordPress.com)
So What is WP_Query Exactly?
Putting together what we learned about Classes and Queries, we can presume that WP_Query is a Class with a lot of Template Tags, those Template Tags all perform functions that query the MySQL database and return pieces of information to us depending upon the Template Tag that we used.
Ugh, Why do I Need to Know WP_Query?
Coming from an HTML/CSS only background and having to stare WP_Query down is intimidating. But you need to know WP_Query if you want to get serious about WordPress Theme development, plugin development, and sometimes even when you’re just modding existing themes. WP_Query allows you to do useful things like display posts within specific categories or write in restrictions for certain user groups, etc.
Your First Ultra Simple WP_Query
Let’s load up our instance of WordPress, I’ve created a basic page template for us to fuss around with WP_Query that includes the header and footer calls for WordPress as well as the essential HTML structure. Outside of the basic setup, there should be nothing else on the page. You can copy and paste the basic template code below, or download it here: Download page-queries.php (PHP)
Once you download the page template, put it into the root folder of your TwentyFifteen theme folder, then create a new page using the WP Query Page template and give it a title (I named mine, “Query Page”) and load up the page on the frontend of your WordPress Instance. You should be looking at something that looks like this:
OK, let’s write our very first WP_Query. This is a really simple one that I mentioned above, it’s get_the_title() which will be used to query our Database and return the title of the page that we’re on. The title you get back should be the title you entered for your page. Type this in between your <header></header> tags, if you downloaded my file you should place this on Line 14:
<?php echo get_the_title(); ?>
Save your file, and refresh the page in your WordPress instance. You should now see this:
If you see the title of your page displayed, congratulations! You’ve just written a super simple query that went into the database, grabbed the title of the page and returned it to you on the page. Let’s go over what exactly we wrote up there. Chances are pretty good that this isn’t the first Template Tag you’ve encountered or even used as you worked with WordPress, but bear with me. PHP is said to be written in blocks. A PHP block begins when you open the block with this <?php and the block ends when you close it with this ?>. Within a PHP block, you may have pure PHP code or a mixture of PHP and HTML. In the above code, we use echo which is our way of telling PHP to display something we tell it to display. In this case, we’re telling PHP to display whatever the value of get_the_title() is. get_the_title() is a WordPress Template Tag (also known as a Method). This Template Tag retrieves the title of the post or page that it was used on. In my case, my page was titled “Query Page”, which is exactly what the Template Tag fetched. As an example of mixing HTML and PHP together, let’s make the title of the page an <h1> like this:
<h1><?php echo get_the_title(); ?></h1>
Notice that I used the <h1> outside of the PHP Block. It is also valid, but less seen, to write it like this:
<?php echo '<h1>' . get_the_title() . '</h1>'; ?>
I prefer to do it the first way wherever possible because it’s faster to type, easier to read (in my opinion) and I’ve personally seen it in use more often in WP development than the second style when we’re trying to style pretty simple and very small PHP Blocks. Both are legitimate styles as far as I know, I just prefer the first and will use it wherever I can. Just so we’re on the same page, the second example does the exact same thing as the first, the only difference is the second one has HTML inside of the PHP Block. When you use HTML inside of a PHP Block, you need to use quotes in order for it to read and display properly. Whenever you have elements in a PHP Block that mix in terms of needing quotes and not needing quotes (in this example, two HTML tags that need quotes and one Template Tag that doesn’t) you have to combine them together in the block by using periods. When we link elements together like this, we are said to be “concatenating” them.
WP_Queries and Arrays
Getting the title of a post or page is fine and dandy, but a lot of the time, you’re going to be using WP_Query in conjunction with arrays to request more than one piece of data from the database. Within PHP, there are three popular forms of arrays: Indexed, Associative and Multidimensional. I’m only going to touch upon the second and third: Associative and Multidimensional, in this tutorial. This is because the majority of the time, you are going to be using Associative or Multidimensional Arrays with WP_Query and if we were to spend time digging into arrays, we’d be here all day. Think of an Associative Array as a collection of keys and their values. A key is an identifier that we associate to a value so we can easily locate the value again. In fact, if you look inside your MySQL database, you’ll notice that many of the pieces of data in it have keys and values associated with those keys. We tend to call this a key value pair (KVP) type of data structure. A Multidimensional Array is an array that holds other arrays. This tutorial focuses on Associative Arrays. An Associative Array in PHP might look something like this, if we were trying to build an array of employees at a company. If you’re interested in testing out arrays, go ahead and plug in this code inside of <div class=”entry-content”>…</div>:
In the above PHP Block, we’re naming our array $employees and defining an array of key and value pairs. The keys would be the employee’s name and the value is the occupation. As proof that we actually created this array and it is, in fact, generating key value pairs, let’s print it out so we can read it. Plug in this appended code:Line 7 is what I’ve freshly added. The echo will output an HTML preformatted tag and its closing pair. Print_r will display the contents of our array. If everything goes well, you should see something like this on your page:
Array ( [Brenda] => accountant [Jonathan] => graphic designer [Aria] => pirate queen )
Print_r is generally used to debug PHP code. We’re not too worried about formalities with this. So long as you got the above output, you’re good to go. Let’s comment out the above code for the $employees array and do something a little more relevant to WordPress. Within <div class=”entry-content”>…</div>, we’re going to add in a different array. An array we might define for the purposes of WP_Query would look more like this:
What we’re doing in the above PHP Block is telling WordPress that we want to create an array called $my_cakes. Within that array, we define what we want based upon existing keys that WordPress recognizes: tag and category. In this example, we want data that contains the value of ‘cake’ within the tags, and the value ‘recipes’ within the categories. After that, we load our array into a variable that we called $get_cakes. Every time you create a variable to hold content in PHP, you precede it with the dollar sign.
The above code won’t display anything at the moment. What it does do is tell the database to locate data tagged with ‘cake’ and categorized under ‘Recipes’. If we were to add more to the above PHP Block, we could get it to return all the Cake Recipe posts we might have in our blog. I’ve created three dummy posts and tagged them with ‘cake’ and created a category called ‘Recipes’. Go ahead and do the same, then append the above code with the following:
Starting from Line 12 is what was freshly added. What we’re doing now is creating a while loop. A while loop in programming is a chunk of code that will perform an action over and over again when a conditional statement (if statement in this example) evaluates as ‘true’. In this case, we’re telling PHP that we want it to reference the query and display the title of the query for each post that it can find that was tagged as ‘cake’ and categorized as ‘recipes’. Here’s a line-by-line of what’s going on: Line 13: Uses an if statement to determine if our $get_cakes query is returning any posts. In other words, if $get_cakes has found any posts that qualify as being tagged ‘cake’ and categorized as ‘recipes’, then evaluate this if statement as being ‘true’. Line 14: Enters into a while loop that states that while $get_cakes has posts (in other words, while the if statement in Line 13 evaluates as true) to go forward to perform the task that begins on Line 15. Line 15: For each post that we will output, reference the values retrieved by $get_cakes. Line 16: Outputs the title followed by a line break based upon the posts we got from $get_cakes. Line 17 – 18: Begins the else statement that will serve as our fallback in case our if statement cannot find any posts using the $get_cakes query. Line 19 – 20: Outputs the text, “sorry, no posts found.” if $get_cakes is empty, or in other words, cannot find any posts matching the key/value we entered in $my_cakes. Line 23: Restores the original post data by resetting the post variable for the main loop. It is important when we write any custom loops in WP, that we call this function. If all goes well, you should be three posts containing your cake recipes show up under the title of the page on your screen when you refresh the browser. So, we’ve successfully filtered out our cake posts from our recipes category. That might come in handy in some instances where you want a particular page to only output certain posts. A Quick Note About Naming Conventions Now’s as good a time as any to mention how WordPress prefers you name objects. I’m used to the general naming convention of camelCase when it comes to programming. WP, for whatever reason, prefers that developers use underscores instead. This doesn’t mean that if you use camelCase in your WP Development that none of your named objects will work, it’s a perfectly acceptable method and if you find yourself writing vanilla PHP, camelCase is the recognized way to go. The underscores are a preference on WP’s part and while we’re playing in their backyard, it’s best to be polite and follow their rules.
Multidimensional Arrays & WP Query
OK, that was fun. How, let’s say we want to display posts under multiple categories instead of just one. I’m going to create three new dummy posts and categorize them all under one new category. It doesn’t matter as much what you this new category, I just call mine “Events”, I want you to also categorize these posts under “Recipes”. You can tag them whatever you want, I just tagged mine under the “cake” tag that I already had going. With your three new posts, let’s write a multidimensional array then load it up in our query and output the titles and excerpts of the posts that were categorized under both ‘Events’ and ‘Recipes’ now, you will need to replace the two category ID numbers with numbers corresponding to your categories (to quickly find what numbers you’re using go to Posts > Categories then mouse over the Events and Recipes categories, you should see their ID numbers in the status bar:
What we’re now doing in the above post is using category__and which is a WP Query category specific parameter. It looks for posts that were listed within the specified categories and will only display posts that are categorized under all of them. In this case, unless a post falls under 20 (recipes) and 30 (events), it won’t get displayed.
The other different thing is under our ‘echo the_title()’ we added an ‘echo the_excerpt()’ to display the excerpts of the posts. If all went well, you should see your three new dummy posts with their titles, and underneath in italics, are the excepts.
Custom Posts & WP Query
All right, we’re going to eventually need to use WP Query with custom post type. Custom Post Types are extremely useful because your content doesn’t always neatly fall under a Post or a Page within WordPress. You’ll also need to know WP Query in case you need to filter, or specifically apply something to a Custom Post Type that was used by a plugin. Like, for instance, if you wanted to display only Testimonials that received a 4/5 or better star rating from a Testimonials Plugin.
At this point, we’re going to need a custom post type, you can create one manually. Or, you can download any of the leading Custom Post Type Plugins if you prefer a faster solution. I can recommend Advanced Custom Fields or Types.
On our test site, let’s create a Custom Post Type called “Clients”, don’t worry about fussing with fields, generating the most bare bones custom post type will be perfectly fine for this tutorial. If you can’t be fussed to go through the motions of installing a plugin or figuring out Custom Post Types right now, then add this code into your functions.php file at the bottom:
After you have your custom post type, create two custom posts, I titled mine, “Hannah” and “George”, both of them have a paragraph of dummy text. All right, let’s use our new custom post type (client_post_type) to output Hannah and George along with an excerpt from each of those entries. Here’s what I’m going to plug into query-page.php:
So most of that should be pretty familiar at this point. The only thing to truly note is the post_type parameter that takes in our custom post type referred to as: “client_post_type”. You can perform this WP Query on other custom post types you might encounter as well.
When to Use WP Query
We’ve been using WP Query for pretty light lifting in this tutorial, and you’ll no doubt find more creative ways to leverage the Class. While it can be useful, you should be aware that querying a lot in your theme or plugin isn’t always the best way to go and there’s a lot more to it than meets the eye, despite the length and the content we went through here, we’re only scratching the surface of what WP Query can do. It’s highly recommended that you check out the WordPress Codex: WP Query on WordPress Codex. Also keep using the test site to play around with WP Query to see what else you can come up with and check out some of the resources I’ve linked below for different WP Query writing styles and uses as well as some more information about when, where and how to use it. Enjoy!