I have been stuck on a particular problem for a while now and have yet to find a way around it. I have custom widgets and for each widget I have added the ability to filter posts based on category AND/OR tags (this functionality works). I am now trying to expand on that by including in each widget a custom field where you can enter the ID of a category you wish to exclude (the custom field is already in the widget and stores user input).
Let me show you what I have so far to help understand:
$args = array(
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => $num_posts,
'cat' => -5,
'tax_query' => array(
'relation' => 'OR',
array(
'taxonomy' => 'category',
'field' => 'id',
'terms' => $category,
),
array(
'taxonomy' => 'post_tag',
'field' => 'id',
'terms' => $tags
),
),
'offset' => 1,
);
As you can see I am taking in two arrays of input for both $category and $tags (this is working fine), but what does not seem to be working is:
'cat' => -5,
If I remove the tax_query array completely, the exclude category works perfectly fine, so it appears that tax_query is overriding the exclude?
If someone could point me in the right direct, that would be great 🙂
Thanks!
The
cat
-parameter is not overwritten bytax_query
. Instead, it is added totax_query
. Thus, using'cat' => -5
, the following array is appended totax_query
:The resulting taxonomy query is built up of three different clauses with the OR-operator. Thus, in your case, adding
'cat' => -5
simply adds the array described above totax_query
, resulting in the query returning that posts that are either$category
, or$tags
Nested tax_query
There is no way to use nested conditionals in
tax_query
. To achieve the conditional you are looking for (posts in a category from$category
or having a tag fromtags
, but in all cases not being in category 5), you would have to hook intoposts_where
and possiblyposts_join
.For anyone interested, the same goes for
meta_query
: this does not support nested queries either.EDIT
Using
posts_where
In response to your comment: to achieve this using
posts_where
, you will want to apply the filter to just the one query for which you want to exclude a category. To do so, add the filter before creating your query, and remove it afterwards:EDIT
Constructing the additional
WHERE
-clauseUsing
get_tax_sql
to construct the additionalWHERE
-clause is useful as you do not have to construct your SQL manually, and the term IDs are automatically converted to term-taxonomy IDs.Just providing an updated answer about Nested Taxonomies because they are indeed supported. The selected answer above is out of date / a little misleading. WordPress Core has supported Nested Taxonomies since v4.1
Taken from the WordPress Codex
https://codex.wordpress.org/Class_Reference/WP_Query#Taxonomy_Parameters