WordPressの検索対象を調整する。pre_get_postsとメインクエリを理解する

CODE 09 pre_get_postsで検索結果のメインクエリだけを調整する条件

PROJECT 002でWordPressの検索画面を整えたとき、見た目だけでなく「検索結果に何を含めるか」も調整しました。そこで使ったのが、検索を実行する前に条件を変更できるpre_get_postsです。

便利な一方、対象を絞らずに使うと、管理画面やサイドバーなど別の一覧まで変える可能性があります。この記事では、検索結果のメインクエリだけを変更する最小例から、三つの条件を一つずつ確認します。

pre_get_postsは検索実行前の条件を変えるフック

WordPressはURLやテンプレートに応じてWP_Queryを作り、必要な投稿を取得します。pre_get_postsは、そのクエリ変数が作られた後、実際の取得処理が走る前に呼ばれるアクションフックです。

検索結果のテンプレート内で別の検索処理を作り直すのではなく、WordPressが用意したメインクエリの条件だけを変更できます。

最小例を子テーマのfunctions.phpで試す

次のコードは、フロント側の検索結果で投稿だけを対象にする最小例です。子テーマのfunctions.phpなど、テーマ更新で消えない場所へ追加します。編集前にバックアップを取り、構文エラー時に戻せる状態で試します。

add_action( 'pre_get_posts', 'maniaru_limit_search_to_posts' );

function maniaru_limit_search_to_posts( $query ) {
    if ( is_admin() ) {
        return;
    }

    if ( ! $query->is_main_query() ) {
        return;
    }

    if ( ! $query->is_search() ) {
        return;
    }

    $query->set( 'post_type', 'post' );
}

保存後、サイトの検索フォームから既知の記事タイトルを検索します。投稿が結果に出て、固定ページが対象外になれば、この例の変更を確認できます。

is_admin()で管理画面を除外する

is_admin()が真なら早い段階で処理を終えます。今回変えたいのは公開サイトの検索結果なので、管理画面の投稿一覧や検索まで同じ条件にしないためです。

フック名だけでは、公開画面専用の処理にはなりません。変更しない範囲を最初に除外すると、後の条件を読みやすくできます。

is_main_query()で主要な一覧だけに絞る

一つのページでは、本文の一覧とは別に、関連記事やサイドバーが独自のクエリを使うことがあります。$query->is_main_query()は、渡されたクエリがページの主要コンテンツを作るメインクエリかを判定します。

pre_get_postsのコールバックでは、引数として受け取ったオブジェクトのメソッドを使います。グローバルを調べるis_main_query()ではなく、$query->is_main_query()と書く点が重要です。

is_search()で検索結果だけに絞る

$query->is_search()を確認しないと、HOMEやカテゴリーアーカイブなど、ほかのメインクエリにもpost_typeの変更が及びます。

今回の条件は「公開画面」「メインクエリ」「検索結果」の三つです。どれか一つでは範囲が広いため、すべてを満たしたときだけ$query->set()を実行します。

set()で変更する値を一つに絞る

最小例で変更するのはpost_typeだけです。値をpostにすると、通常の投稿が検索対象になります。投稿と特定のカスタム投稿タイプを含める場合は、配列で指定できます。

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

manualは例のスラッグです。存在しない投稿タイプをそのままコピーせず、自分の環境で登録されている値へ置き換えます。

検索画面と管理画面の両方で結果を確認する

保存後は、対象になる投稿と対象外になる固定ページをそれぞれ検索します。検索結果の件数とリンク先を確認し、管理画面の投稿検索が変更前と同じように使えることも確認します。

  • 公開サイトの検索結果だけが変わる
  • 通常の投稿が検索結果に表示される
  • 対象外にした種類は表示されない
  • カテゴリーやHOMEの一覧に影響しない
  • 管理画面の検索に影響しない

変更後に結果がゼロになった場合は、検索語だけでなく、指定したpost_typeが実在するか、三つの条件が意図した画面で真になるかを確認します。

クエリを変える前に対象範囲を決める

pre_get_postsで大切なのは、値を設定する一行より、その前の条件です。変更したい画面と、変更してはいけないクエリを先に分けることで、検索結果だけを小さく調整できます。

MANIARUでは検索画面の入口・結果・見つからない場合を整えたうえで、この処理を検索対象の調整に使いました。画面側の設計は「WordPressの検索画面を整える」、実装の背景はPROJECT 002 STEP 07にまとめています。

仕様の詳細は、WordPress公式のpre_get_postsリファレンスでも確認できます。