Site icon Tips Note by TAM

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

何はともあれpre_get_posts

WordPressを使用してWebサイトを構築しようとしたとき、次のような要望に出くわすことはよくあることでしょう。検索結果の一覧ページでは記事の件数を30件表示したい。過去記事の月別アーカイブは全件表示したい。サイト内検索の結果は特定のカスタム投稿タイプだけで絞り込みたい。etc…

それらを実現するにはpre_get_postsがオススメです。以前、その手の実装にはquery_postsが使用されており、今もWEB上にはquery_postsを使用したティップスがたくさんあります。ですが今現在query_postsの使用は推奨されていません。我らが愛しいCodexにもこのように書かれています。

ひとことで言うと、query_posts() は決して使うべきではありません。

テンプレートタグ/query posts - WordPress Codex 日本語版

なぜ使うべきでないかという細かいお話は丸ごとCodexに預けるとして、今回は代替として台頭したpre_get_postsの使い方について、簡単に解説いたします。

最大表示件数を変更する

まずは実例です。例えば、あなたはブログの検索結果ページで最大表示件数を30件にしたいと考えています。そのためにはどうすればよいか。まずは以下のサンプルをfunctions.phpに貼り付けてみてください。

<?php
  function myPreGetPosts( $query ) {
      if ( is_admin() || ! $query->is_main_query() ){
          return;
     }
       if ( $query->is_search() ) {
         $query->set('posts_per_page', 30);
     }
   }
   add_action('pre_get_posts','myPreGetPosts');
?>

これだけです。これでもう、検索結果の最大表示件数は30件になりました。あっという間ですね。

では、簡単に解説します。

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

これは管理画面であるか、あるいはメインクエリでない場合に素のクエリを保つためのおまじないです。これを唱えておかないと「なんだか身に覚えのない場所でpre_get_postsが動いている!」なんてことになりかねません。何はともあれ、必ずいれておきましょう。

if ( $query->is_search() ) {
    $query->set('posts_per_page', 30);
}

そして、これがミソです。$query->is_search()で「検索結果ページだったら」とページを限定し、$query->set('posts_per_page', 30)で最大表示件数を30件に指定しています。

投稿タイプを制限する

$query->setは必要なだけ追加できます。たとえば最大表示件数を30件にした上で、表示結果はカスタム投稿タイプ『hoge』からのみ取得したい、という場合は以下のようになります。

<?php
 function myPreGetPosts( $query ) {
      if ( is_admin() || ! $query->is_main_query() ){
          return;
     }
       if ( $query->is_search() ) {
         $query->set('posts_per_page', 30);
         $query->set('post_type', 'hoge');
        }
   }
   add_action('pre_get_posts','myPreGetPosts');
?>

$query->set()で使用できるパラメータはquery_postsとほとんど変わりません。詳しくはWP_Queryを参照してください。

参考リンクなど

今回は基本的な実例のみを紹介しましたが、たとえばGET値を組み合わせて使うとより設定の幅は広がりますし、絞り込み検索などもpre_get_postsを使用して実装することが可能です。pre_get_postsをより深く知りたいあなたには、以下のサイトなどもオススメです。

ぜひシンプルですてきなpre_get_postsを活用してみてください。