本文へ移動

WP_Query解説

query_postsを使わないほうがいい理由
|WP_Query・pre_get_postsとの違い

テーマを編集していてquery_posts()を見つけたら、そのまま真似せず「現在の投稿一覧を変えるコードか、別の一覧を追加するコードか」を確認します。メイン一覧ならpre_get_posts、記事下やサイドバーの別一覧ならWP_Queryまたはget_posts()が基本です。

Huddly Huddly 投稿日: 2026年8月28日 読了目安: 3分

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へ、そのまま貼るコードではありません。

PHPhome.php避けたいquery_postsの例
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または機能プラグインに置く例です。対象画面と実行条件を確認し、検証環境で試してから本番へ反映してください。

PHPfunctions.php投稿一覧ページのメインクエリをpre_get_postsで調整する例
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_Queryget_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へ、そのまま貼るコードではありません。

PHPsingle.phpquery_postsではなくWP_Queryで別一覧を作る例
$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. 1
    そのコードがメイン一覧を変えているのか、追加一覧を作っているのか確認する
  2. 2
    メイン一覧ならpre_get_posts、追加一覧ならWP_Queryまたはget_posts()を候補にする
  3. 3
    query vars、URL条件、ページネーションを保ったまま置き換える
  4. 4
    1ページ目と2ページ目、archive、search、404、feedで回帰確認する

query_posts()と一緒にあるwp_reset_query()も、WP_Queryのループへ変えた場合はwp_reset_postdata()へ変わることがあります。取得方法と後処理をセットで見直してください。

公式資料で確認したいポイント

公式資料でquery_posts()の注意、pre_get_postsの対象限定、WP_Queryget_posts()の違いを確認できます。

公式リンク

公式ドキュメント

最後に確認したいこと

  • query_postsはメインクエリを置き換える関数だと理解している
  • メイン一覧を変えるならpre_get_postsを検討できる
  • 別一覧を作るならWP_Queryまたはget_postsを検討できる
  • query_postsを見つけた時に目的を確認してから置き換え先を選べる
  • WP_Queryの別ループ後にwp_reset_postdata()を置いた
WP Query BuilderBuilderで条件を組み直す条件を選び、WP_Queryのコードを画面で作れます。Builderでクエリを作る

この記事を書いた人

Huddly

Web制作 / フロントエンドエンジニア

WordPressとフロントエンド実装で迷いやすい点を、公式情報と検証結果を分けながら、初学者にも追いやすい順序で整理しています。

この記事の検証情報

検証環境

WordPress
7.1
PHP
8.3.33
テーマ
wpq-media + DDEV
対象
カスタム投稿 / taxonomy / meta_query

更新履歴

  • 2026年8月28日 初回公開

この記事を活用する

あとで見返す・共有する

お気に入りに保存できます。役に立ったポイントは、いいねや共有で教えてください。

任意のご支援 役に立ったときだけ、活動を応援できます OFUSEはサイト・記事制作に使います。支援の有無で、読める内容や使える機能は変わりません。