Formulate a url to show posts with both taxonomy terms
-
26-04-2021 - |
Question
I would like to show an archive of posts that have two taxonomy terms in common. So for example, I'd like to show all posts that have both the terms "sauce" and "cheese" in the custom food
taxonomy.
The trick is that I'd like to do this using the url. The closest I've come is with:
example.com?food[]=sauce&food[]=cheese
Upon inspecting the $query from the pre_get_posts
filter, I can see that:
WP_Tax_Query::__set_state(array(
'queries' =>
array (
0 =>
array (
'taxonomy' => 'food',
'terms' =>
array (
0 => 'sauce',
1 => 'cheese',
),
'field' => 'slug',
'operator' => 'IN',
'include_children' => true,
),
),
So then I change the operator
to AND
like so:
add_action('pre_get_posts', function($query) {
$query->tax_query->queries[0]['operator'] = 'AND';
});
But my results are always including posts that have at least one term instead of posts that have all terms.
According to Query Monitor, the main query is as such (and you can see that it's looking for posts that have either of the two term IDs.
SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
LEFT JOIN wp_term_relationships
ON (wp_posts.ID = wp_term_relationships.object_id)
WHERE 1=1
AND ( wp_term_relationships.term_taxonomy_id IN (6,9) )
So, how can I formulate a url to get only posts with both taxonomy-terms?
Solution 2
When I registered my taxonomy, I left out the argument for 'rewrite', which then defaulted to true
. So by default, WordPress wanted to rewrite the url as /food/whatever/
. The tricky thing was that it did accept the format ?food=whatever
, but wouldn't accept two different terms in that format when joined with a plus.
The solution was to specify the rewrite arg of register_taxonomy()
like so:
register_taxonomy( 'food', 'post', [
...
'rewrite' => [
'slug' => 'filter',
'with_front' => false,
],
...
]);
And then I can use /food/sauce+cheese
like @jdm2112 and the docs specify.
OTHER TIPS
Looks like you can define the AND
logical operator with the URL parameters, specifically adding the "+" between your terms like this:
url?taxonomy=term1+term2
This will ensure that only posts containing all terms listed are returned.
Example: https://example.com/blog?food=sauce+cheese
[tax_query] => WP_Tax_Query Object
(
[queries] => Array
(
[0] => Array
(
[taxonomy] => food
[terms] => Array
(
[0] => sauce
)
[field] => slug
[operator] => IN
[include_children] => 1
)
[1] => Array
(
[taxonomy] => food
[terms] => Array
(
[0] => cheese
)
[field] => slug
[operator] => IN
[include_children] => 1
)
)
[relation] => AND
Notice the relation is definitely AND between the terms.
In local testing, I can confirm the returned posts are only those that contain BOTH terms.