WordPress のサイト内検索をプラグインなしでカスタマイズする方法

カスタマイズ,
WordPressカテゴリー
Pocket

サイト内検索を拡張してくれる有名プラグインもあるのですが、今回は functions.php に記述して検索条件をカスタマイズする方法をご紹介します。

プラグインを使うと本文の検索結果がでてこない?

実はこの方法を実践する前に、Search Everything と Relevanssi を試してみたのですが、何故か本文やタイトルに入っているキーワードにも関わらず、検索結果が『なし』になる状態が発生していました。

プラグインのおかけで、カテゴリー名やタグ名は問題なく検索結果にでてきましたが、細かいキーワードへの対応ができないほうが嫌だったので、今回の方法を導入してみました。

検索条件に、カテゴリー名、タグ名、投稿者名を追加

WordPress標準のサイト内検索では、『投稿ページ』と『固定ページ』のタイトル本文抜粋が検索対象となっています。
下記を functions.php に記述することで、検索範囲を カテゴリー名タグ名投稿者名まで広げることができます。

/**
 * サイト内検索の範囲に、カテゴリー名、タグ名、を含める
 */
function custom_search($search, $wp_query) {
global $wpdb;
 
//サーチページ以外だったら終了
if (!$wp_query->is_search)
 return $search;

if (!isset($wp_query->query_vars))
 return $search;
 
// ユーザー名とか、タグ名・カテゴリ名も検索対象に
$search_words = explode(' ', isset($wp_query->query_vars['s']) ? $wp_query->query_vars['s'] : '');
 if ( count($search_words) > 0 ) {
   $search = '';
   foreach ( $search_words as $word ) {
     if ( !empty($word) ) {
       $search_word = $wpdb->escape("%{$word}%");
       $search .= " AND (
           {$wpdb->posts}.post_title LIKE '{$search_word}'
           OR {$wpdb->posts}.post_content LIKE '{$search_word}'
           OR {$wpdb->posts}.post_author IN (
             SELECT distinct ID
             FROM {$wpdb->users}
             WHERE display_name LIKE '{$search_word}'
             )
           OR {$wpdb->posts}.ID IN (
             SELECT distinct r.object_id
             FROM {$wpdb->term_relationships} AS r
             INNER JOIN {$wpdb->term_taxonomy} AS tt ON r.term_taxonomy_id = tt.term_taxonomy_id
             INNER JOIN {$wpdb->terms} AS t ON tt.term_id = t.term_id
             WHERE t.name LIKE '{$search_word}'
           OR t.slug LIKE '{$search_word}'
           OR tt.description LIKE '{$search_word}'
           )
       ) ";
     }
   }
 }
 
 return $search;
 }
 add_filter('posts_search','custom_search', 10, 2);

 

※投稿者名を検索条件から外したい場合は、この部分を消してください。

OR {$wpdb->posts}.post_author IN (
 SELECT distinct ID
 FROM {$wpdb->users}
 WHERE display_name LIKE '{$search_word}'
 )

 

参考サイト:[WordPress] ユーザー名とか、タグ名・カテゴリ名も検索対象に

pre_get_posts で 検索結果のクエリーをカスタマイズ

続いて、検索時のクエリーに条件を追加します。
以下の内容を function.php に追記して保存します。

function change_posts_paging($query) {

// 管理画面やメインクエリーでない場合は除外
 if ( is_admin() || ! $query->is_main_query() ) {
   return;
 }
 // 検索結果ページ
 if ( $query->is_search() ) {
    // 公開されてる記事のみ検索
    $query->set( 'post_status', publish );
    // 投稿のみ検索
    $query->set( 'post_type', post );
    // 表示したくないカテゴリーID
    $query->set( 'category__not_in', 1 );
    // 表示したくない投稿ID。arrayで複数指定可。
    $query->set( 'post__not_in', array( 1, 2, 3, 4, 5 ) );
    // 検索結果の表示順
    $query->set( 'order', DESC );
   return;
  }
 }
 add_action( 'pre_get_posts', 'change_posts_paging' );

投稿タイプを追加する場合は、array 型で記述します。
カスタムポストタイプ(ex. movie )を含む場合もここに追加します。

$query->set( 'post_type', array( 'post', 'page', 'movie' ) );

※その他、具体的なパラメータは 関数リファレンス/WP Query を参照してください。

 

サイト内検索を行い、狙い通りの結果がでてきたら成功です。

参照サイト

[WordPress]pre_get_postsを使いこなす!pre_get_posts使い方まとめ

pre_get_postsでメインクエリを制御する