WordPressでメインクエリやその他のWP_Query
インスタンスがデータベースに問い合わせる直前に、そのクエリパラメータを動的に変更したいと思ったことはありませんか?そんな時に絶大な威力を発揮するのがpre_get_posts
アクションフックです。このフックを使いこなすことで、テーマのテンプレートファイルを直接編集することなく、様々なページの表示条件を柔軟にカスタマイズできます。
pre_get_posts
は、WordPressの表示制御をより高度に行うための重要なフックであり、特にテーマ開発やサイトの細かなカスタマイズにおいて必須の知識と言えるでしょう。
pre_get_postsフックの基本的な使い方
pre_get_posts
フックは、WP_Query
オブジェクトが実際に投稿を取得する前に実行されます。このフックにコールバック関数を登録し、その関数内で渡される$query
オブジェクトのプロパティを変更することで、クエリ結果を操作します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?php function my_custom_pre_get_posts( $query ) { // 管理画面のクエリは対象外にし、メインクエリのみを対象とするのが一般的 if ( ! is_admin() && $query->is_main_query() ) { // 例: ホームページの場合のみ、投稿表示件数を3件にする if ( $query->is_home() ) { $query->set( 'posts_per_page', 3 ); } // 例: 'event' カテゴリーのアーカイブページの場合、投稿タイプ 'event_cpt' のみ表示する if ( $query->is_category('event') ) { $query->set( 'post_type', array( 'event_cpt' ) ); // 必要であれば、元の 'post' タイプを上書きしないように注意 // $query->set( 'post_type', 'event_cpt' ); とすると 'event_cpt' のみになる } } } add_action( 'pre_get_posts', 'my_custom_pre_get_posts' ); ?> |
重要なのは、is_admin()
や$query->is_main_query()
を使って、意図しないクエリ(管理画面のクエリや、ウィジェット等で使われるサブクエリなど)を変更してしまわないように条件分岐を行うことです。
pre_get_posts
で設定可能な主要パラメータ一覧
pre_get_posts
で使用できる主要なパラメータ($query->set()
で設定可能なもの)を機能別に分類しました。各パラメータの説明の冒頭には、その利用頻度や重要度を星の5段階評価で示しています。星の数の目安は以下の通りです。
★★★★★:ほぼ全ての開発で頻繁に利用され、基本かつ非常に重要なパラメータ
★★★★☆:高頻度で利用され、多くの一般的なカスタマイズで役立つ重要なパラメータ
★★★☆☆:中程度の頻度で利用され、特定の機能を実現する際に便利なパラメータ
★★☆☆☆:利用頻度はやや低めですが、特定の要件や細かな制御を行いたい場合に役立つパラメータ
★☆☆☆☆:利用頻度は低く、非常に限定的な状況や高度なカスタマイズでのみ使用されるパラメータ
カテゴリ | 設定可能なパラメータ ($query->set()の第一引数) |
説明 | 一般的な設定値の例 |
---|---|---|---|
投稿タイプ関連 | post_type |
★★★★★ 取得する投稿タイプを指定します。メインクエリの投稿タイプを変更する際によく使います。 |
'page' , 'event' , array('post', 'event') |
post_status |
★★★☆☆ 取得する投稿のステータスを指定します。通常は ‘publish’ ですが、’future’ (予約投稿) などを含めることも。 |
'publish' , array('publish', 'future') |
|
投稿数・順序関連 | posts_per_page |
★★★★★ 1ページあたりに表示する投稿数を変更します。アーカイブページなどで特に多用されます。 |
12 , -1 (全件表示) |
orderby |
★★★★☆ 投稿の並び順の基準を変更します。日付、タイトル、カスタムフィールド値など。 |
'title' , 'modified' , 'rand' , 'meta_value_num' |
|
order |
★★★★☆ 投稿の並び順(昇順・降順)を指定します。 orderby とセットで。 |
'ASC' , 'DESC' |
|
meta_key |
★★★☆☆orderby で'meta_value' や'meta_value_num' を指定した場合の、並び替え基準となるカスタムフィールドのキー。 |
'event_start_date' , 'product_price' |
|
offset |
★★☆☆☆ 指定した数だけ投稿をスキップして表示します。ページネーションとの併用には注意が必要です。 |
1 (最初の1件をスキップ) |
|
タクソノミー関連 | cat |
★★★☆☆ 特定のカテゴリーID(またはその除外)で絞り込みます。 |
5 (ID:5のみ), -7 (ID:7を除外) |
category_name |
★★★☆☆ カテゴリースラッグで絞り込みます。 |
'news' , 'featured-event' |
|
category__in / category__not_in |
★★★☆☆ 複数のカテゴリーIDを含める/除外する場合に使用します。 |
array(2, 6) |
|
tag / tag_id / tag__in / tag__not_in |
★★★☆☆ タグによる絞り込み。カテゴリーと同様のパラメータ群があります。 |
'wordpress' , array(10, 12) |
|
tax_query |
★★★★★ 複数のタクソノミー条件や、カスタムタクソノミーで複雑な絞り込みを行う場合に必須です。 |
下記サンプルコード参照 | |
カスタムフィールド関連 | meta_key |
★★★☆☆ 特定のカスタムフィールドキーを持つ投稿で絞り込む(値の指定は meta_value )。 |
'is_featured_post' |
meta_value / meta_value_num |
★★★☆☆meta_key で指定したカスタムフィールドの値で絞り込みます。 |
'yes' , 100 |
|
meta_query |
★★★★★ 複数のカスタムフィールド条件で複雑な絞り込みを行う場合に必須です。 |
下記サンプルコード参照 | |
投稿ID関連 | post__in |
★★★☆☆ 指定した投稿IDの配列に一致する投稿のみを表示します。 |
array(10, 25, 30) |
post__not_in |
★★★★☆ 特定の投稿(例:現在の投稿、除外したい記事リスト)を除外するのによく使います。 |
array(get_the_ID()) (現在の投稿を除外) |
|
日付関連 | date_query |
★★★☆☆ 特定の日付範囲や条件で投稿を絞り込みます。 |
下記サンプルコード参照 |
著者関連 | author / author_name |
★★★☆☆ 特定の著者の投稿に絞り込みます。 |
1 , 'johndoe' |
author__in / author__not_in |
★★☆☆☆ 複数の著者IDを含める/除外する場合に使用します。 |
array(2, 5) |
|
検索関連 | s |
★★★★☆ 検索結果ページで、検索キーワードを変更したり、特定のキーワードを強制的に追加したりする場合に使います。 |
'new keyword' |
ページネーション関連 | ignore_sticky_posts |
★★★☆☆ 先頭固定表示の投稿を通常の投稿と同じように扱うか ( true )、特別扱いするか (false 、デフォルト) を指定します。 |
true |
サンプルコード集
pre_get_posts
フックの具体的な活用例をいくつか紹介します。
1. ホームページのブログ一覧の表示件数を変更
1 2 3 4 5 6 7 8 |
<?php function my_homepage_posts_per_page( $query ) { if ( ! is_admin() && $query->is_home() && $query->is_main_query() ) { $query->set( 'posts_per_page', 6 ); // ホームページでは6件表示 } } add_action( 'pre_get_posts', 'my_homepage_posts_per_page' ); ?> |
2. 特定のカスタム投稿タイプのアーカイブページの表示順をタイトル昇順に変更
1 2 3 4 5 6 7 8 9 |
<?php function my_custom_cpt_archive_order( $query ) { if ( ! is_admin() && $query->is_main_query() && $query->is_post_type_archive( 'my_portfolio' ) ) { $query->set( 'orderby', 'title' ); $query->set( 'order', 'ASC' ); } } add_action( 'pre_get_posts', 'my_custom_cpt_archive_order' ); ?> |
3. 検索結果から特定の投稿タイプ(例: ‘page’)を除外
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?php function exclude_pages_from_search( $query ) { if ( ! is_admin() && $query->is_main_query() && $query->is_search() ) { $post_types = $query->get('post_type'); if ( empty( $post_types ) ) { // デフォルトは 'any' もしくは 'post' $post_types = array('post'); // 明示的に 'post' を指定 } if ( is_array( $post_types ) ) { // 'page' を除外 (もしあれば) $post_types = array_diff( $post_types, array('page') ); // もし 'any' が含まれていたら、明示的に検索対象としたい投稿タイプを指定する必要がある if ( in_array('any', $post_types) ) { $post_types = array('post', 'news', 'event_cpt'); // 検索対象にしたい投稿タイプ } } elseif ( $post_types === 'page' ) { // 'page' のみ検索対象だった場合 $post_types = ''; // 検索対象なし (または 'post' などに) } $query->set( 'post_type', $post_types ); } } add_action( 'pre_get_posts', 'exclude_pages_from_search' ); ?> |
注意: post_type
を変更する際は、既存のクエリがどのような投稿タイプを対象にしているかを考慮し、適切にマージまたは上書きする必要があります。
4. 特定のカテゴリーアーカイブで、さらにタグで絞り込む (tax_query)
「ニュース」カテゴリーのアーカイブページで、「重要」タグがついた記事のみ表示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?php function filter_news_category_by_tag( $query ) { if ( ! is_admin() && $query->is_main_query() && $query->is_category( 'news' ) ) { $tax_query = $query->get( 'tax_query' ); // 既存のtax_queryを取得 if ( ! is_array( $tax_query ) ) { $tax_query = array(); } // 'AND' 条件でタグによる絞り込みを追加 $tax_query['relation'] = 'AND'; $tax_query[] = array( 'taxonomy' => 'post_tag', 'field' => 'slug', 'terms' => 'important', ); $query->set( 'tax_query', $tax_query ); } } add_action( 'pre_get_posts', 'filter_news_category_by_tag' ); ?> |
よくある質問 (FAQ)
- Q1:
pre_get_posts
と、自分でnew WP_Query()
を使うのはどう違いますか? - A1:
pre_get_posts
はWordPressが自動的に生成する「メインクエリ」(例: カテゴリーアーカイブページや検索結果ページなど)や、その他の既存のクエリを変更するためのフックです。一方、new WP_Query()
は、完全に新しい独自のクエリを作成して投稿データを取得する場合に使います(例: サイドバーに特定の条件の人気記事一覧を表示するなど)。メインの表示内容を変更したい場合はpre_get_posts
、追加で別の情報を取得したい場合はnew WP_Query()
と使い分けるのが一般的です。 - Q2:
$query->is_main_query()
のチェックはなぜ重要ですか? - A2: WordPressの1つのページ表示の中では、メインのコンテンツを表示するためのクエリ(メインクエリ)以外にも、ナビゲーションメニュー、ウィジェット、プラグインなどによって複数のサブクエリが実行されることがあります。
$query->is_main_query()
のチェックを怠ると、これらの意図しないサブクエリまで変更してしまい、サイトの表示が崩れたり、予期せぬ動作を引き起こしたりする可能性があるためです。多くの場合、カスタマイズしたいのはメインクエリです。 - Q3:
pre_get_posts
を使う上での注意点はありますか? - A3:
最も重要なのは、前述の通り、変更対象のクエリを適切に絞り込むことです (
!is_admin()
,$query->is_main_query()
, 各種条件タグなど)。また、設定するパラメータによっては、無限ループを引き起こしたり、他のプラグインやテーマの機能と競合したりする可能性もゼロではありません。変更を加えた後は、必ずサイトの各所で表示確認を行うようにしましょう。特にページネーションが正しく動作するかどうかの確認は重要です。
まとめ
pre_get_posts
アクションフックは、WordPressのクエリをテーマファイルに手を加えることなく、安全かつ柔軟に変更できる非常に強力なツールです。この記事で紹介したパラメータや使い方を参考に、ぜひあなたのWordPressサイトの表示を思い通りにカスタマイズしてみてください。
私たちは、ここ埼玉県川越市から、全国のWordPressサイトオーナー様や開発者様に向けて、高度なカスタマイズ、プラグイン開発、そして技術的なサポートや保守サービスをご提供しています。WordPressに関するお困りごとがございましたら、どうぞお気軽にご相談ください。