Using URL parameters, list posts from category and custom taxonomy

For example, http://example.com/?cat=6&tag=books lists posts that belong to category ID 6 and tagged ‘books’ (i.e. posts that satisfy both conditions).

Similarly, http://example.com/feed/?cat=6&tag=books does the same for feeds.

Read More

Now, lets say that my blog has a custom taxonomy called ‘edition’, with terms ‘usa’, ‘uk’, ‘china’, and so on, under it. The URL http://example.com/?edition=usa,china lists posts that belong to both editions ‘usa’ and ‘china’.

And http://example.com/category/cars/?edition=usa lists those posts from category ‘Cars’ that also belong to the custom taxonomy term ‘usa’.

The problem

I use the code below in my functions.php:

add_filter('pre_get_posts','better_editions_archive');
function better_editions_archive( $better_editions_query ) {

    /* Looks like this line needs to be changed, not sure how */
    if ( $better_editions_query->is_tax( 'edition' ) && $better_editions_query->is_main_query() ) {

        $better_editions_terms = get_terms( 'edition', array( 'fields' => 'ids' ) );
        $better_editions_query->set( 'post_type', array( 'post' ) );
        $better_editions_query->set( 'tax_query',
            array(
                'relation' => 'OR',
                array(
                    'taxonomy' => 'edition',
                    'field' => 'id',
                    'terms' => $better_editions_terms,
                    'operator' => 'NOT IN'
                )
            )
        );

    }

    return $better_editions_query;
}

The code makes sure that if a post is unassigned to any Edition (i.e. if a post is not assigned to any term that belongs to the custom taxonomy ‘edition’), the post is shown/listed under all term archives/feeds of the custom taxonomy ‘edition’.

Now, http://example.com/category/cars/?edition=usa only lists posts that belong to the category ‘cars’ and specifically marked ‘usa’ (a term belonging to the custom taxonomy ‘edition’). It doesn’t show those posts that aren’t assigned to any term in the custom taxonomy ‘edition’. How do I fix this?

(PS: Setting default terms for posts isn’t an option, as we may add more editions later on.)


Solved but…

I’ve worked out a solution which you can see as an answer to this question. The bounty still stands, so feel free. 🙂

Related posts

2 comments

  1. In general circumstances, using URL parameters, you can list posts that belong to a specific category AND a custom taxonomy, like this:

    http://example.com/category/cars/?edition=usa
    

    Where, category is the Category base you are using for categories on your site (WordPress Dashboard > Settings > Permalinks > Category base); edition is the custom taxonomy’s base/slug; and usa is a term under the custom taxonomy.

    If you want to include more than one category/custom taxonomy, these might help:

    http://example.com/category/cars/?edition=usa,india
    http://example.com/?category_name=cars,books&edition=usa,india
    

    And Feeds:

    http://example.com/category/cars/?edition=usa,india&feed=rss2
    http://example.com/?category_name=cars,books&edition=usa,india&feed=rss2
    

    Further Reading:


    BUT…

    As explained in my question, mine is a complex case, so I’ve developed a simple work-around. Here goes…

    1. The code block in the question makes sure that if a post is unassigned to any Edition (i.e. if a post is not assigned to any term that belongs to the custom taxonomy ‘edition’), the post is shown/listed under all term archives/feeds of the custom taxonomy ‘edition’.

      BUT NOW, I removed that code. Then created a new term under the custom taxonomy ‘edition’, called ‘intl’ (International). Any post that want to be displayed under all Editions will be assigned to ‘intl’. But how do I make sure that all posts assigned to ‘intl’ show up in all term archives/feeds of my custom taxonomy?

      For that, I now use this code (goes in functions.php):

      add_filter('pre_get_posts','better_editions_archive');
      function better_editions_archive( $query ) {
          if ( $query->is_tax( 'edition' ) && $query->is_main_query() ) {
              $query->set( 'post_type', array( 'post' ) );
              $query->set( 'tax_query',
                  array(
                      'relation' => 'OR',
                      array(
                          'taxonomy' => 'edition',
                          'field' => 'slug',
                          'terms' => 'intl',
                          'operator' => 'IN'
                      )
                  )
              );
          }
          return $query;
      }
      

      So now, for instance, http://example.com/edition/usa/ lists posts that belong to either ‘usa’ or ‘intl’ (which are terms under my custom taxonomy ‘edition’). Its feed, http://example.com/edition/usa/feed/ does the same as well.

    2. Back to the main problem of the question. How do I list posts that belong to a specific category AND an edition, using URL parameters?

      For example, how do I list posts that belong to category ‘cars’ AND edition ‘usa’?

      This is what the URL should look like: http://example.com/category/cars/?edition=usa,intl (since we also want those posts that are shown under all editions i.e. those posts assigned to term ‘intl’). As for feeds: http://example.com/category/cars/feed/?edition=india,intl

    That’s it!

    (Special thanks to @kaiser for his help.)


    Notes

    If you strictly want to modify the main query/loop right within the template, e.g. taxonomy-edition.php (in my case), here’s an example as to how it can be done:

    <?php
    $edition_term = get_term( get_queried_object(), 'edition' )->slug;
    $better_editions = new WP_Query(
        array(
            'post_type' => 'post',
            'tax_query' => array(
                array(
                    'taxonomy' => 'edition',
                    'field' => 'slug',
                    'terms' => array( $edition_term, 'intl' )
                )
            )
        )
    );
    ?>
    
        <?php /* Blah, Blah, Blah! */ ?>
    
    <?php if ( $better_editions->have_posts() ) : ?>
    
        <?php /* Start the Loop */ ?>
        <?php while ( $better_editions->have_posts() ) : $better_editions->the_post(); ?>
            <?php get_template_part( 'content', get_post_format() ); ?>
        <?php endwhile; wp_reset_postdata(); ?>
    
    <?php else : ?>
    
        <?php /* Blah, Blah, Blah! */ ?>
    
    <?php endif; ?>
    

    Nonetheless, unless you really, really have to, go with pre_get_posts.

  2. You may have to look into using wp_query. in which you set your own query to display any category you like, and then when done, reset it to the default behaviour.

Comments are closed.