I want to amend the search so if say I have taxonomy called \"author\" and add a term of \"Ian Rankin\" to a post, if I search for \"Ian Rankin\", I want that post to come up.
It could also be done by using MySQL's EXISTS function with a subquery that joins term_relationships with terms. I have created the following snippet and put it into functions.php:
// Search titles and tags
function and_extend_search( $search, &$wp_query ) {
global $wpdb;
if ( empty( $search ))
return $search;
$terms = $wp_query->query_vars[ 's' ];
$exploded = explode( ' ', $terms );
if( $exploded === FALSE || count( $exploded ) == 0 )
$exploded = array( 0 => $terms );
$search = '';
foreach( $exploded as $tag ) {
$search .= " AND (
($wpdb->posts.post_title LIKE '%$tag%')
OR EXISTS
(
SELECT
*
FROM
$wpdb->term_relationships
LEFT JOIN
$wpdb->terms
ON
$wpdb->term_relationships.term_taxonomy_id = $wpdb->terms.term_id
WHERE
$wpdb->terms.name LIKE '%$tag%'
AND
$wpdb->term_relationships.object_id = $wpdb->posts.ID
)
)";
}
return $search;
}
add_filter('posts_search', 'and_extend_search', 500, 2);
You can alter the search query using filter hooks to join the taxonomy tables.
e.g. to also search on the 'author' taxonomy
First join the taxonomy tables
function tax_search_join( $join )
{
global $wpdb;
if( is_search() )
{
$join .= "
INNER JOIN
{$wpdb->term_relationships} ON {$wpdb->posts}.ID = {$wpdb->term_relationships}.object_id
INNER JOIN
{$wpdb->term_taxonomy} ON {$wpdb->term_taxonomy}.term_taxonomy_id = {$wpdb->term_relationships}.term_taxonomy_id
INNER JOIN
{$wpdb->terms} ON {$wpdb->terms}.term_id = {$wpdb->term_taxonomy}.term_id
";
}
return $join;
}
add_filter('posts_join', 'tax_search_join');
then find the search term in the taxonomy 'author'
function tax_search_where( $where )
{
global $wpdb;
if( is_search() )
{
// add the search term to the query
$where .= " OR
(
{$wpdb->term_taxonomy}.taxonomy LIKE 'author'
AND
{$wpdb->terms}.name LIKE ('%".$wpdb->escape( get_query_var('s') )."%')
) ";
}
return $where;
}
add_filter('posts_where', 'tax_search_where');
and finally group the results by post id to avoid duplicate results because of the join
function tax_search_groupby( $groupby )
{
global $wpdb;
if( is_search() )
{
$groupby = "{$wpdb->posts}.ID";
}
return $groupby;
}
add_filter('posts_groupby', 'tax_search_groupby');