カテゴリーやタグを検索出来るようにする

カテゴリーやタグを検索出来るようにする

WordPressのサイト内検索でタグやカテゴリーを含めて検索する方法を紹介します。

デフォルトの検索対象はタイトル、抜粋からとなっています。

そこにカテゴリーやタグといったタームも含めて検索できる方法を紹介します。

クエリを変更する

カテゴリーやタグを含めた検索をする場合にはSQLのjoin句でタームのテーブルを結合する必要があります。

「wp_posts」テーブルのIDに対応させてターム名のテーブルを持ってくる必要があります。

「wp_posts」に結合する順番としては「wp_term_relationships」「wp_term_taxonomy」「wp_terms」の順になります。

「wp_posts」のIDと対応しているのは「wp_term_relationships」のobject_idです。

さらに「wp_term_relationships」のterm_taxonomy_idと「wp_term_taxonomy」のterm_taxonomy_idが対応しています。

「wp_term_taxonomy」のterm_idと「wp_terms」のterm_idが対応しています。

そして「wp_terms」のname列にターム名が入っています。

これをコードにすると以下のようになります。

「posts_join」フィルターを利用します。

add_filter( 'posts_join', function( $join, $query_obj ) {
	if( is_admin() || $query_obj->is_main_query() ) {
		return $join;
	}

	$join .= " LEFT JOIN (select object_id, term_taxonomy_id from wp_term_relationships) AS trs";
	$join .= " ON (wp_posts.ID = trs.object_id )";
	$join .= " LEFT JOIN (select term_taxonomy_id, term_id from wp_term_taxonomy) AS tt";
	$join .= " ON (trs.term_taxonomy_id  = tt.term_taxonomy_id)";
	$join .= " LEFT JOIN (select term_id, name from wp_terms) AS t";
	$join .= " ON ( tt.term_id = t.term_id)";

	return $join;
}, 10, 2 );

この状態では投稿IDが重複している状態ですので、重複を削除するためにDISTINCT句を入れます。

DISTINCT句には「posts_distinct」フィルターを使用します。

add_filter( 'posts_distinct', function( $distinct, $query_obj ) {
	if( is_admin() || $query_obj->is_main_query() ) {
		return $distinct;
	}

	$distinct = " DISTINCT";

	return $distinct;
}, 10, 2);

これで準備は整いました。

後は検索で「$_GET[‘s’]」に渡された値に対して検索するためのwhere句の作成です。

今回は検索ワードのLIKE検索とします。

WHERE句には「posts_where」フィルターを使用します。

add_filter( 'posts_where', function add_where( $where, $query_obj ) {

	if( is_admin() || $query_obj->is_main_query() ) {
		return $where;
	}

	global $wpdb;

	$s = $query_obj->get('s');
  $like = '%'. $wpdb->esc_like( $s ). '%';
  $where .= $wpdb->prepare( " OR t.name LIKE %s", $like );

	return $where;
}, 10, 2 );

これで検索ワードでカテゴリーやタグといったタームの検索もできます。

カテゴリーやタグなど制限をかけたい場合には「wp_term_taxonomy」テーブルを結合する際にwhere句を使用して変更してください。