Unable to combine “search value” and “tax_query” using WP_Query

This is a result of a problematic GROUP BY clause that’s added to WP_Query when tax_query is present. It conflicts with the s parameter. You can remove the GROUP BY entirely to fix it, but you shouldn’t do this for every WP_Query. I use the following class often to approach this:

/**
 * Search Within a Taxonomy
 * 
 * Support search with tax_query args
 *
 * $query = new WP_Query( array(
 *  'search_tax_query' => true,
 *  's' => $keywords,
 *  'tax_query' => array( array(
 *      'taxonomy' => 'country',               
 *      'field' => 'id',                      
 *      'terms' => $country,   
 *  ) ),
 * ) );
 */
class WP_Query_Taxonomy_Search {
    public function __construct() {
        add_action( 'pre_get_posts', array( $this, 'pre_get_posts' ) );
    }

    public function pre_get_posts( $q ) {
        if ( is_admin() ) return;

        $wp_query_search_tax_query = filter_var( 
            $q->get( 'search_tax_query' ), 
            FILTER_VALIDATE_BOOLEAN 
        );

        // WP_Query has 'tax_query', 's' and custom 'search_tax_query' argument passed
        if ( $wp_query_search_tax_query && $q->get( 'tax_query' ) && $q->get( 's' ) ) {
            add_filter( 'posts_groupby', array( $this, 'posts_groupby' ), 10, 1 );
        }
    }

    public function posts_groupby( $groupby ) {
        return '';
    }
}

new WP_Query_Taxonomy_Search();

Now you can add the custom search_tax_query to WP_Query objects that you want this functionality added to. For example:

$query = new WP_Query( array(
    'search_tax_query' => true,
    's' => $keywords,
    'tax_query' => array( array(
        'taxonomy' => 'country',               
        'field' => 'id',                      
        'terms' => $country,   
    ) ),
) );

To explain what’s going on here, the problem is caused by an unintended result of the GROUP BY MySQL clause that’s added to WP_Query objects with a tax_query argument. When you combine this with search, we don’t want/need this clause. If you remove it, the search results will work as you expect: posts matching a search query (s) within a taxonomy (tax_query).

Leave a Comment