Filtering WP_Query result by category

Using WP_Query, I need to gather a selection of posts that are both Category1 and Category2. I want this selection to include Category1 and all of its subcategories (Category3 and Category4), as long as they are also labeled Category2, even if they aren’t labeled Category1.

Categories:

Name          ID     Parent
Category1     1
Category2     2
Category3     3      1
Category4     4      1

Posts:

ID     Categories
1      1,2
2      2,3
3      2,4


Now, if I were to use WP_Query to find posts in just Category1 it seems to find all three posts including Post2 and Post3 since Category3 and Category4 are subcategories of Category1 even though the posts aren’t Category1.

new WP_Query(
        array(
            'cat' => 1
        )

However, if I use ‘category__and’ to find posts that are both Category1 and Category2

new WP_Query(
        array(
            'category__and' => array(1, 2)
        )

it only finds Post1 that has both Category1 and Category2, but it won’t find Post2 that is Category2 and Category3 or Post3, even though Category3 and Category4 are subcategories of Category1.

Is there a way I can take the result of this:

new WP_Query(
        array(
            'cat' => 1
        )

Which finds posts that are Category1 AND subcategories of Category1, even if they aren’t also Category1…

And then filters it to only include those posts that also are Category2?

Thanks for any suggestions.

2 Answers
2

The category parameters of WP_Query does not have this type of logic. category__and and category__in does not return posts in child categories of the set categories.

I would suggest that you make use of the tax_query parameters in WP_Query, which have the logic you are looking for. The relation parameter has two possible values, AND and OR

relation (string) – The logical relationship between each inner taxonomy array when there is more than one. Possible values are ‘AND’, ‘OR’. Do not use with a single inner taxonomy array.

Also, by default, child terms are included in a tax_query, and that is what you need.

include_children (boolean) – Whether or not to include children for hierarchical taxonomies. Defaults to true.

You can do something like this:

$args = array(
    'post_type' => 'post',
    'tax_query' => array(
    'relation' => 'AND',
        array(
            'taxonomy' => 'category',
            'field'    => 'term_id',
            'terms'    => 1,
        ),
        array(
            'taxonomy' => 'category',
            'field'    => 'term_id',
            'terms'    => 2,
            'include_children' => false,
        ),
    ),
);
$query = new WP_Query( $args );

What this code does, it looks for posts that are in category 1 and in its child categories, also, it checks whether these posts from category 1 and its child categories are also in category 2. The list of posts returned will be posts that are in category 1 or any of its child categories and which is also in category 2.

I have excluded the child categories from category 2, but you can remove this if needed.

Leave a Comment