query_postsを見つけたら、用途に合う方法へ置き換える
query_posts()は、別の投稿一覧を追加するための普通の取得関数ではなく、現在のページ用のメインクエリを置き換える関数です。WordPress公式も、テーマやプラグインではできる限り避けるよう案内しています。
投稿一覧やアーカイブのメイン一覧を変えるならpre_get_posts、記事下などに別一覧を足すならWP_Queryまたはget_posts()が基本です。まず古いコードがどちらを変えているかを確認し、用途に合う方法へ置き換えます。
まず、どの一覧を変えるコードか確認する
古いテーマや検索で見つけたコードでは、一覧件数を変えるためにquery_posts()が使われていることがあります。最初に、そのコードが投稿一覧やアーカイブのメイン一覧を変えているのか、記事下やサイドバーに別一覧を足しているのかを確認します。
公式リファレンスは、query_posts()がメインクエリを完全に上書きするため、テーマやプラグインでは避けるよう案内しています。
| 問題になりやすい点 | 何が起きるか | 代わりに考えるもの |
|---|---|---|
| メインクエリを置き換える | 現在のページ用に用意された取得条件を後から差し替えてしまう | pre_get_posts |
| ページネーションが崩れやすい | pagedなどを自分で考慮しないとページ送りが合わない | pre_get_posts |
| 追加のSQLが発生しやすい | すでに取得された結果を捨てて、もう一度取得する形になりやすい | pre_get_posts |
| 別一覧との区別がつきにくい | メイン一覧なのか追加一覧なのかコードから読みづらい | WP_Query / get_posts |
先に、現在のページの一覧を変えたいのか、別枠の一覧を足したいのかを分けます。
query_posts()の問題は、投稿を取得できるかどうかではなく、WordPressが持っている現在のページの文脈を後から置き換えてしまう点です。メインクエリを後から差し替えると分かりにくくなる
メインクエリと追加のWP_Queryの違いはWP_Queryの役割と使い方で先に整理できます。別ループを作った後の後処理はwp_reset_postdata()が必要な理由へ続けてください。
WordPressはURL、表示設定、カテゴリー、検索語などからメインクエリを先に作ります。query_posts()はテンプレートまで来てからそれを置き換えるため、元のアーカイブ条件やページの文脈が追いにくくなります。
次は古いhome.phpで見かける形です。投稿一覧の件数を変える意図でも、テンプレートからメインクエリを置き換えています。
クラシックテーマのテンプレート(またはテンプレートパーツ)で、一覧を表示したい位置に置く例です。投稿本文やfunctions.phpへ、そのまま貼るコードではありません。
query_posts( [ 'posts_per_page' => 5,] ); if ( have_posts() ) { echo '<ul>'; while ( have_posts() ) { the_post(); printf( '<li><a href="%1$s">%2$s</a></li>', esc_url( get_permalink() ), esc_html( get_the_title() ) ); } echo '</ul>';} wp_reset_query();最後にwp_reset_query()を書いても、既に実行されたメインクエリとは別に再取得し、置き換える構造は変わりません。ページ送りではpagedも考慮する必要があります。
メインクエリを変えたいならpre_get_postsを使う
メイン一覧を変えるなら、pre_get_postsで実行前のクエリ条件を調整します。
たとえば投稿一覧ページの記事数を5件にしたい場合は、functions.phpなどに次のように書きます。管理画面や別のクエリに影響しないように、is_admin()、query objectのis_main_query()、is_home()で対象を絞ることが大切です。
子テーマのfunctions.phpまたは機能プラグインに置く例です。対象画面と実行条件を確認し、検証環境で試してから本番へ反映してください。
function wpq_limit_home_posts( $query ) { if ( is_admin() || ! $query->is_main_query() ) { return; } if ( $query->is_home() ) { $query->set( 'posts_per_page', 5 ); }}add_action( 'pre_get_posts', 'wpq_limit_home_posts' );$query->is_main_query()でメインクエリだけを対象にし、is_admin()で管理画面を除外しています。
ここでのis_home()は「投稿一覧ページ」を指し、固定フロントページと常に同じではありません。管理画面の「ホームページの表示」によって対象URLが変わるため、フロントページだけを変えたい場合は要件と条件分岐を見直してください。pre_get_postsの条件を広く書きすぎると、アーカイブや検索結果、feedまで変わることがあります。
別の一覧を追加したいならWP_Queryかget_postsを使う
関連記事やサイドバーの新着など、別枠の一覧ならWP_Queryかget_posts()を使います。メインクエリを変える必要はありません。
| やりたいこと | 選びやすい方法 | 理由 |
|---|---|---|
| 投稿一覧やアーカイブのメイン一覧を変えたい | pre_get_posts | メインクエリが実行される前に対象を限定して調整できる |
| 記事下に関連記事を追加したい | WP_Query | 独立したqueryとしてページ送りや状態を扱える |
| 少量の投稿配列を取得したい | get_posts() | 既定では5件で、総ページ数を使わない小さな取得に向く |
| 古いコードでquery_postsを見つけた | 目的を確認して置き換える | メイン一覧か追加一覧かで正しい代替が変わる |
get_posts()はWP_Queryの単なる高速版ではありません。少量の投稿配列を受け取る用途に向き、既定の取得件数は5件です。取得後にsetup_postdata()を使ってテンプレートタグの参照先を切り替えた場合は、最後にwp_reset_postdata()が必要です。
次は、現在の記事を除外し、新着3件を別クエリで表示する例です。
クラシックテーマのテンプレート(またはテンプレートパーツ)で、一覧を表示したい位置に置く例です。投稿本文やfunctions.phpへ、そのまま貼るコードではありません。
$current_post_id = get_queried_object_id(); $related_query = new WP_Query( [ 'post_type' => 'post', 'post_status' => 'publish', 'posts_per_page' => 3, 'post__not_in' => [ $current_post_id ], 'ignore_sticky_posts' => true,] ); if ( $related_query->have_posts() ) { echo '<ul>'; while ( $related_query->have_posts() ) { $related_query->the_post(); printf( '<li><a href="%1$s">%2$s</a></li>', esc_url( get_permalink() ), esc_html( get_the_title() ) ); } echo '</ul>';} else { echo '<p>表示できる投稿はありませんでした。</p>';} wp_reset_postdata();$related_queryだけを回し、the_post()を使った後はwp_reset_postdata()で投稿データを戻します。
古いquery_postsコードを見つけた時の置き換え方
古いコードは機械置換せず、メインループ直前なのか、記事下やサイドバーの小さな一覧なのかを確認します。
query_postsを見つけた時の確認順
- 1そのコードがメイン一覧を変えているのか、追加一覧を作っているのか確認する
- 2メイン一覧ならpre_get_posts、追加一覧ならWP_Queryまたはget_posts()を候補にする
- 3query vars、URL条件、ページネーションを保ったまま置き換える
- 41ページ目と2ページ目、archive、search、404、feedで回帰確認する
query_posts()と一緒にあるwp_reset_query()も、WP_Queryのループへ変えた場合はwp_reset_postdata()へ変わることがあります。取得方法と後処理をセットで見直してください。
公式資料で確認したいポイント
公式資料でquery_posts()の注意、pre_get_postsの対象限定、WP_Queryとget_posts()の違いを確認できます。
公式リンク
公式ドキュメント
最後に確認したいこと
- query_postsはメインクエリを置き換える関数だと理解している
- メイン一覧を変えるならpre_get_postsを検討できる
- 別一覧を作るならWP_Queryまたはget_postsを検討できる
- query_postsを見つけた時に目的を確認してから置き換え先を選べる
- WP_Queryの別ループ後にwp_reset_postdata()を置いた
この記事の検証情報
検証環境
- WordPress
- 7.1
- PHP
- 8.3.33
- テーマ
- wpq-media + DDEV
- 対象
- カスタム投稿 / taxonomy / meta_query
更新履歴
- 2026年8月28日 初回公開
この記事を活用する
あとで見返す・共有する
お気に入りに保存できます。役に立ったポイントは、いいねや共有で教えてください。


