1

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?

3
  • Tried wordpress.stackexchange.com/questions/25999/… but it didn't work for me
    – JakeParis
    Mar 16, 2021 at 18:42
  • How is your statement that modifies the logic to AND called? Is it also called with pre_get_posts?
    – jdm2112
    Mar 16, 2021 at 20:06
  • @jdm2112 Thanks for looking, I've updated the code, and yes, that is wrapped in the pre_get_posts action.
    – JakeParis
    Mar 17, 2021 at 13:21

2 Answers 2

2

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.

4
  • Ok, that does work... but only when I have permalinks rewriting turned off. With permalink writing on, ?food=sauce+cheese is getting rewritten to /food/sauce. I also tried setting rewrite=>false in the register_taxonomy() call, but it still removed the second item and changed it to ?food=sauce
    – JakeParis
    Mar 18, 2021 at 15:52
  • Right. So you want to retain the query string parameters instead of having WP rewrite these taxonomy archive URLs? Not sure if there is a way to work that with the WP_Rewrite API or not. Essentially do not rewrite the URL if the request meets certain conditions? If so, please add to your question above for the sake of clarity.
    – jdm2112
    Mar 18, 2021 at 22:58
  • Actually, no I don't actually care what the url looks like. In my comment, I only meant that when I join two terms with the plus sign (as you suggested), the second one gets stripped out. And that happens when pretty-permalinks are on (as they are on the vast majority of sites). It does not happen with no pretty permalinks. I don't have any custom rewrite logic. When you tested, did you happen to do with raw query strings or pretty permalinks?
    – JakeParis
    Mar 22, 2021 at 13:32
  • On my test site permalinks are on, using a custom structure "/blog/%postname%". My testing uses the tax and terms as a query string and the URL is not rewritten - example.local/blog?food=sauce+cheese
    – jdm2112
    Mar 22, 2021 at 14:05
0

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.