So far in this series you've learned how to use WP_Query
to create custom queries for use in your theme or plugins.
In most cases, you'll use WP_Query
with a completely new set of arguments which are separate from that in the main query, but what if you want to include the main query in your arguments?
Examples of when you might want to do this include:
- on a category or taxonomy page, displaying only posts of one post type
- on a category page, displaying posts with the current category and another category or a tag or taxonomy term
- on a page for a post type, just displaying posts with certain metadata
I could go on—there are plenty of opportunities for combining the main query with your own custom query.
I'm going to demonstrate this with three examples: the first one will be a simple example with one loop; the second will use foreach
to output multiple loops, one for each post type; and the third will output two post types on a category archive by using two separate queries.
Defining a Variable Based on the Main Query
However you're going to combine your main query with WP_Query
, you need to store the current query object in a way that makes it easy to use in your WP_Query
arguments. The easiest way to do this is by assigning it to a variable.
You do this before defining your WP_Query
arguments, like so:
$mainquery = get_queried_object();
The get_queried_object()
function returns the currently queried object, whatever that may be. On a single post, it will just return the post object, while on an archive it will return the category, tag, term object or whatever object relates to the archive. It returns the ID of the queried object.
You can then use this $mainquery
variable in your WP_Query
arguments. Now let's take a look at some examples.
Example 1: Displaying Only Posts of One Post Type on a Category Page
Let's say your site has a custom post type added to it and you've enabled categories for that custom post type. On the category archive for each category, you don't want to display posts: instead you want to display posts of your new post type—let's call it product
.
Your query might look something like this:
<?php $mainquery = get_queried_object(); $args = array ( 'category_name' => $mainquery->slug, 'post_type' => 'product' ); // 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(); ?>
Because the category_name
parameter I've used above takes the category slug as its argument, you need to add ->slug
after the variable to output the category slug.
This gives you a query which fetches posts of the product
post type from the database with the currently queried category. You'd use it on the category.php
page template.
Note: You could also achieve this result using the pre_get_posts
hook to amend the main query, combined with a conditional function to check for category archives.
Example 2: Combining the Main Query With WP_Query and foreach to Output Multiple Loops
The next example will output all of the posts for the current category page, but instead of showing them all in one block it will separate them by post type.
This means you can sort your post types into blocks or columns on your page using CSS, or just separate them out into different lists.
To do this, you'd use the following code:
<?php $mainquery = get_queried_object(); $post_types = get_post_types(); foreach ( $post_types as $post_type ) { $args = array( 'category_name' => $mainquery->slug, 'post_type' => $post_type ); // 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(); } ?>
This uses the $mainquery
variable we used before, but it also adds a $post_types
variable to store all of the post types registered on the site, and a $post_type
variable to store each individual post type in turn.
Example 3: Two Separate Queries for Two Post Types
The final example is similar to the second one, but separates out the post types into two separate queries, each with its own distinct loop. This gives you more control over what's displayed for each, so you could display posts differently from products, maybe including a featured image for products or giving them a different layout.
Let's say your site has the product
post type registered, with categories enabled for it, and you're also writing blog posts with the same categories. On each category archive page you want to display the most recent ten posts, and then you want to display a list of all products in the same category.
To do this, you'd use something like this code:
<?php $mainquery = get_queried_object(); // First query arguments for posts. $args = array ( 'category_name' => $mainquery->slug, 'post_type' => 'post', 'posts_per_page' => '10' ); // 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(); // Second query arguments for products. $args = array ( 'category_name' => $mainquery->slug, 'post_type' => 'product', 'posts_per_page' => '-1' ); // 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'd then write each loop differently to output different data for each post type.
Summary
As you can see from the examples above, it's possible to use WP_Query
not only to create completely custom queries separate from the main query, but also to incorporate the currently queried object and create more powerful queries on archive pages.
The examples above can also be done with other archive types: for taxonomies, authors, dates and more. See if you can come up with more possibilities!
Comments