WordPressの投稿取得を自在に操れるpre_get_posts の便利な使い方まとめ

※本記事のコードは参考用です。使用前にご自身で動作確認をお願いします。

WordPress で投稿の一覧をカスタマイズしたいとき、非常に強力なのが pre_get_posts フィルターフックです。
このフックを使えば、テーマのテンプレートをいじらなくても、投稿・カスタム投稿の取得条件を柔軟に変更することができます。

本記事では、pre_get_posts の基本と、実際によく使われるカスタマイズ事例を一覧形式で紹介します。

pre_get_posts とは

pre_get_posts は WordPress が投稿を取得する「直前」に実行されるフックです。
このタイミングでクエリ(WP_Query オブジェクト)を変更することで、投稿一覧に表示される内容を自在にコントロールできます。

pre_get_postsの基本形

function my_query_customization( $query ) {
    if ( is_admin() || ! $query->is_main_query() ) return;
    // ここで条件を変更
}
add_action( 'pre_get_posts', 'my_query_customization' );

よく使われるカスタマイズ例

1. カスタム投稿タイプのアーカイブで表示件数を変更

個人的にpre_get_postsで最もよく使うコードです。カスタム投稿タイプが複数存在し、各自の表示件数を変更するコードです。
以下のコードでは、eventというカスタム投稿タイプの表示件数を20件に設定しています。

if ( $query->is_post_type_archive( 'event' ) && $query->is_main_query() ) {
    $query->set( 'posts_per_page', 20 );
}

2. トップページに特定のカテゴリーのみ表示

トップページでは投稿一覧に、newsカテゴリだけを表示したいときなどに便利です。

if ( ( $query->is_home() || $query->is_front_page() ) && $query->is_main_query() ) {
    $query->set( 'category_name', 'news' );
}

3. カスタム投稿タイプをアーカイブに含める

通常投稿アーカイブに、例えばeventというカスタム投稿も表示したいときなどに利用できます。

if ( $query->is_archive() && $query->is_main_query() ) {
    $query->set( 'post_type', array( 'post', 'event' ) );
}

4. タグ付き投稿を除外する(例:非表示タグ)

特定の投稿は一覧荷表示したくない場合、例えば「非公開」「非表示」などのタグをつけ、それを投稿を一覧に出さないようにするといったことも可能です。

if ( $query->is_main_query() && ! is_admin() ) {
    $query->set( 'tag__not_in', array( 123 ) ); // 除外したいタグのID
}

5. 年別アーカイブを年度別に変更する

年別アーカイブは通常1月から12月の範囲ですが、4月から翌3月までに変更するコードです。学校・行政などの公的機関などでは要望が多いのではないでしょうか。

if ( $query->is_year() && $query->is_main_query() ) {
    $y = get_query_var( 'year' );
    $query->set( 'date_query', array(
        array(
            'after'     => "$y-04-01 00:00:00",
            'before'    => ($y + 1) . "-03-31 23:59:59",
            'inclusive' => true,
        ),
    ));
    $query->set( 'year', null );
}

6. 特定の検索結果だけカスタマイズする

検索結果にカスタム投稿タイプを含めたり、件数を変えたりすることができます。

if ( $query->is_search() && $query->is_main_query() ) {
    $query->set( 'posts_per_page', 50 );
    $query->set( 'post_type', array( 'post', 'news' ) );
}

7. 特定のカスタムフィールド値で絞り込む

例えば、今日以降のイベントだけを表示したい場合などに便利です。

if ( $query->is_main_query() && is_post_type_archive( 'event' ) ) {
    $query->set( 'meta_query', array(
        array(
            'key'     => 'event_date',
            'value'   => date('Y-m-d'),
            'compare' => '>=',
            'type'    => 'DATE'
        )
    ));
}

注意点:is_main_query()! is_admin() を忘れずに

pre_get_posts を使ってクエリをカスタマイズする場合、管理画面への影響を防ぐために is_admin() を使うことが必須です。また、メインクエリだけを対象にするには is_main_query() もセットで使いましょう。

if ( ! is_admin() && $query->is_main_query() ) {
    // クエリのカスタマイズ
}
  • ! is_admin():管理画面では何も変更しないようにする
  • $query->is_main_query():メインクエリ(ループ)だけを対象にして、サブクエリ(ウィジェットなど)は無視

まとめ

pre_get_posts を使えば、テンプレートファイルを複雑に書き換えることなく、投稿の取得条件を柔軟に変更できます。
特に一覧ページのカスタマイズや条件による出し分けが必要な場面では、非常に便利な仕組みです。

参考

pre_get_posts – Hook | Developer.WordPress.org