メインクエリを操作して投稿を表示させる pre_get_posts

更新2022/01/11

WordPressでサイトを構築するとき、一覧表示のカスタマイズは欠かせないもの。

トップページでは5件だけ表示して、カテゴリーページでは10件表示にする。検索結果には特定の投稿タイプのみ表示させたい。
こういった要望があったときに使えるのが、pre_get_postsです。

pre_get_posts とは

投稿した情報はデータベースに保存されています。投稿記事を表示させるには、データベースから表示させたい記事を指定しなければなりません。
この時に「表示させたい記事の条件」をクエリと言います。

WordPressはアクセスしたURLによって自動的に表示させる投稿データを取得しています。
URLによって自動的に条件を決めている内容を「メインクエリ」、それ以外にこちらから指定する条件を「サブクエリ」と言います。

pre_get_posts はWordPressがアクセスしたURLをもとに「メインクエリで投稿を取得する前に」処理を行いたいときに使う アクションフック というものです。

アクションフックとは?

アクションフックは「とあるイベントが発生するときに実行する処理を追加するもの」です。WordPressのデフォルトの動きに変更を加えるために用意されています。

「このイベントがあったら」→「このアクションをしてね」というイメージです。
「このイベントがあったら」の部分にアクションフックが入ります。

pre_get_posts は名前の通り「投稿を取得する前」というイベントを指しています。

add_action('pre_get_posts', 'my_preget_posts');
// このようなイメージ↓↓↓↓↓↓
add_action('投稿を取得する前に', 'my_preget_postsの処理を行う');

コード概要

私はいつもこのようなコードを書いています。

function my_preget_posts($query) {
  if (is_admin() || ! $query->is_main_query()){
    return;
  }
  if ($query->is_home()) {
     $query->set('posts_per_page', 3);
     return;
  }
  if ($query->is_category()) {
    $query->set('order', 'DESC');
    $query->set('orderby', 'date');
  }
}
add_action('pre_get_posts', 'my_preget_posts');

まず一番始めにこのようなコードがあります。

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

これは管理画面を表示しているとき、もしくは現在のクエリがメインクエリでなければ動作をキャンセルする、という処理です。このコードは必ずつけます。

$query にはクエリ情報が入っていて、この中身を変更することでメインクエリを変更することができます。

基本の書き方は、if分でページを指定し、$query->set() で表示内容を設定します。
この $query->set() の部分を変更してカスタマイズしていきます。(「クエリを→セットする」ということですね)

$query->set('パラメータ', パラメータに対応する値);

$query->set('posts_per_page', 3); であれば、「表示件数を最大3件にする」というコードです。
posts_per_page‘ の他にパラメータはたくさん用意されています($WP_Query と同じパラメータを使用できます)

リファレンスや参考記事などで確認しながら、必要なものを設定してください。

【パラメータ参照】WordPress Developer Resources

必要なクエリセットを書いたら add_action() を使って実行させます。

add_action('pre_get_posts', 'my_preget_posts');

add_action() は第一引数に「アクションフック名」、第二引数に「実行する関数名」を記述します。

この例ではm第一引数の pre_get_posts で「投稿を取得する前」を指定し、第二引数の my_preget_posts で「記述した内容を実行する」となります。

表示する最大件数を設定する

最大表示件数を設定するパラメータは posts_per_page です。対応する値は「最大表示件数」。

if ($query->is_home()) {
   $query->set('posts_per_page', 3);
   // $query->set('posts_per_page', 最大表示件数)
   return;
}

これでトップページの投稿一覧は、最大3件を表示するようになります。表示件数を変えたい場合は最後の数字の部分を変更します。

表示順序を設定する

表示順序は、orderorderby パラメータを使用します。

  if ($query->is_category()) {
    $query->set('order', 'DESC');
    $query->set('orderby', 'modified');
  }

このコードでは表示順序を日付の降順(新しいものから順番)にしています。

order は順序(昇順・降順)、orderby は並び順をどの部分で決定するかを設定します。

順序はASCまたはDESC。
ASC(昇順)… 1 2 3
DESC(降順)… 3 2 1

日付での順序ならASCが古いものから表示、DESCは新しいものから表示されます。初期値がDESCなので、昇順にしたい場合のみASCを設定すれば大丈夫です。

並び順のパラメータはタイトルやランダム、コメント数といったものがあります。
【参照】順序づけパラメータリスト

特定のカテゴリー・タグを除外する

カテゴリーの場合は category__not_in、タグの場合は tag__not_in を使います。

// 特定のカテゴリー除外
if ($query->is_home()) {
  $query->set('category__not_in', array(3, 5));
}
// 一つの場合でもarrayを使う
if ($query->is_home()) {
  $query->set('category__not_in', array(5));
}
// 特定のタグ除外
if ($query->is_home()) {
  $query->set('tag__not_in', array(3, 5));

値は配列で渡さなければならないため、設定値が一つしかなくても array() を使います。

カテゴリーの場合はマイナス記法というものも使えます。タグには使えません。

// カテゴリーのみ、値に「-」をつけて除外にする方法がある
if ($query->is_home()) {
  $query->set('cat', '-3,-5');
}

特定のタクソノミーを除外する

タクソノミーの場合は、他のものより設定が多くなります。

if ($query->is_home()) {
  $tax_query = array(
    array(
      'taxonomy'  => 'tax_name',
      'terms'     => array(5, 6),
      'operator'  => 'NOT IN',
    ),
  );
  $query->set('tax_query', $tax_query);
}

pre_get_posts は固定ページでは使えない

「固定ページ」で pre_get_posts は使えません。

pre_get_posts は単一の固定ページのリクエスト(ページテンプレート)に対するクエリを変更するのに用いるべきではありません。なぜなら ‘is_page’、’is_singular’、’pagename’ および他のプロパティ(pretty パーマリンクを使っているかどうかによる)が parse_query() メソッドによってセットされた後だからです。詳しくは クエリ概要 を見てください。
これと同様に、pre_get_posts はテンプレートファイル(例えば archive.php)内では動作しません。なぜならクエリが完了した後だからです。
これらの設定に精通していて、かつ設定を調整しようと望むのでなければ、ページテンプレート内で new WP_Query を使って単一の固定ページのリクエスト(ページテンプレート)に対するクエリを変更するのを推奨します。

プラグイン API/アクションフック一覧/pre get posts – WordPress Codex 日本語版

固定ページで投稿情報を取得したい場合は、「WP_Query」や「get_posts」を使用します。

WP_Query」や「get_posts」の使い方はこちら↓

【関連記事】サブループで任意の投稿一覧を表示

メインループの書き方もまとめているのでご参考ください

【関連記事】投稿一覧を表示させるメインループの使い方

カテゴリー : WordPress

TOPへ