Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to amend wordpress search so it queries taxonomy terms and category terms?

Tags:

php

wordpress

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. I guess at the moment it only searches titles and content. How can I make it search terms too?

like image 836
Claire Avatar asked Nov 21 '12 11:11

Claire


People also ask

How do I show taxonomy terms in WordPress?

Custom display of Terms in a WordPress Taxonomy $args = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'all'); $terms = wp_get_post_terms( $post_id, $taxonomy, $args );

What is the difference between taxonomy and category WordPress?

What is a Taxonomy. In broad terms, any method of grouping of posts is known as a Taxonomy. A Category and Tags are two methods of grouping posts that are present in WordPress by default. hese are the Taxonomies that are present by default in WordPress.

How do I add custom taxonomy to WordPress?

In WordPress, you can create (or “register”) a new taxonomy by using the register_taxonomy() function. Each taxonomy option is documented in detail in the WordPress Codex. After adding this to your theme's functions. php file, you should see a new taxonomy under the “Posts” menu in the admin sidebar.


2 Answers

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');
like image 80
Tom Avatar answered Oct 03 '22 01:10

Tom


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. This applies to at least WordPress Version 5.3.1:

// 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);
like image 20
Andi Avatar answered Oct 02 '22 01:10

Andi