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
).