Keyword search limited to specific post type filtered by multiple custom taxonomies?

It’s fairly inefficient to use query_posts and I often find it’s more trouble than it’s worth. Instead, to set the post type you can just have a hidden input inside the form with name ‘post_type’ and value (in this example) ‘news’. WordPress handles the rest.

Unfortunately it is not so easy with taxonomies (maybe I’ve missed a trick?). However, rather than redo-ing the search with query_posts, you can just use the pre_get_posts filter which runs before the database is queried to filter by taxonomy term.

The following assumes your news category has name ‘news-category’ and your post type is ‘news’:

(First remember to remove your query_posts stuff from the search template – as this just over-rides the default query WordPress performs).

HTML markup

This is the form that displays your search:

<form action="" method="get">
<?php
 //Get all (non-empty) terms for taxonomy 'news-category'
 $args = array('orderby' => 'name','order' => 'ASC');
 $categories = get_terms( 'news-category', $args );

 //Display checkbox for each term
 foreach ($categories as $category) {
       echo '<input type="checkbox" name="my-filter-terms[]" value="'.$category->slug.'">'.esc_html($category->name);
  }
  ?>

    <!-- Hidden input to set post type to news-->
    <input type="hidden" name="post_type" value="news" />

    <!-- Visible input for search term -->
    <input type="text" name="s" value="" />

    <!-- Submit button -->
    <input type="submit" />
 </form>

I’ve used my-filter-terms to store the array of slugs of the checked terms. (It would probably be better to register a custom variable, but I’ll leave that for now. I had hoped to be able to use the default taxonomy query variable but it didn’t seem to work).

Filter the Search

The post type and search term will be automatically handled. The following is to filter by taxonomy term. This goes in your theme’s functions.php:

add_filter('pre_get_posts','my_filter_the_search',10,1);
function my_filter_the_search($query){

    //If the query is a search AND taxonomy terms are set, filter by those terms:
    if($query->is_search() && isset($_GET['my-filter-terms'])){
        //Get array of slugs of checked terms
        $terms = (array) $_GET['my-filter-terms'];

        //Tax_query array
        $tax_query = array(array(
                    'taxonomy' => 'news-category',
                    'field' => 'slug',
                    'terms' => $terms,
                    'operator' => 'IN',
                )); 

        //Tell the query to filter by tax
        $query->set('tax_query', $tax_query  );
    }
    return $query;
}

The operator is set to IN. This means it searches any posts in any one of the checked terms. You could set it to AND to search posts which are in all the checked terms.