「query_posts」「WP_Query」「get_posts」の違いと使い分け完全ガイド

WordPress

WordPressで投稿一覧を出すコードを調べると、 「query_posts()」「WP_Query()」「get_posts()」 の3種類があります。
どれも「投稿を取得する関数」ですが、実はそれぞれの動作の仕組みや影響範囲がまったく異なります。

使い方を誤ると・・・
  • ページネーションが動かなくなる
  • 「先頭に固定表示」が効かない
  • メインクエリが壊れて他のパーツに影響する

といったトラブルを引き起こすこともあります。

本記事では、この3つの関数の違い・使い分け・おすすめの実装方法をわかりやすく解説します。
コードを書くたびに「どれを使えばいいんだっけ?」と悩む方は、この記事でスッキリ整理できます。

3つの関数の役割と基本的な違い

WordPressで投稿を取得する関数は複数ありますが、実はそれぞれ「どのクエリを扱うか」が大きな違いです。

関数名役割メインクエリへの影響ページネーション固定表示(Sticky)対応主な用途
query_posts()すでに存在するメインクエリを書き換えるあり(上書きする)壊れることが多い効かないことがある簡易的な調整(非推奨)
WP_Query()新しいクエリを独立して作るなし正常に使えるデフォルトでは無効(設定で可)サブループ・独自一覧の出力
get_posts()投稿を配列で取得する(軽量)なし使えない(全件固定)無効スライダーやサイドバーなど軽い用途
ざっくりまとめると・・・
  • query_posts() … 「今あるメインクエリを書き換える」ので壊れやすい。基本は使わない。
  • WP_Query() … 最も汎用的で、独自ループを作るならこれ。
  • get_posts() … テンプレート内で軽くデータだけ取りたいとき用。

3つとも「投稿を取得する」ことはできますが、WordPress内部で扱う仕組み(メインクエリ・サブループ・配列処理)が異なるため、使い分けが重要です。

query_posts() の特徴と注意点(非推奨の理由)

query_posts() は、WordPress が最初に作成した メインクエリ($wp_query)を上書き する関数です。
一見シンプルに投稿の取得条件を変更できるように見えますが、実際には多くの不具合を引き起こす原因になります。

メインクエリを上書きしてしまう

通常、WordPress ではページごとに「どんな投稿を表示するか」が決まっており、
これをメインクエリ($wp_query)が管理しています。

query_posts() を使うとこのメインクエリを再実行して上書きしてしまうため、
ページネーションが効かなくなる条件付きタグ(is_home, is_category など)が壊れる といった問題が発生します。

「先頭に固定表示」やプラグインの挙動に影響する

さらに、query_posts() は内部的に WP_Query を再生成する形をとるため、固定表示(sticky posts)やプラグインによるクエリフックが正しく動作しないことがあります。

対処法:pre_get_posts か WP_Query() に書き換える

もしメインクエリの条件を変更したいだけなら、テンプレート階層でのメインクエリを書き換える pre_get_posts フック を使うのが安全です。

//例:1ページに表示する最大投稿数を6件に変更
function custom_modify_main_query($query) {
  if ( is_home() && $query->is_main_query() ) {
    $query->set('posts_per_page', 6);
  }
}
add_action('pre_get_posts', 'custom_modify_main_query');

また、メインクエリに影響を与えず独自に投稿を取得したい場合は、次に紹介する WP_Query() を使うのがベストです。

WP_Query() の特徴と使い方

WP_Query は WordPress の投稿を取得するためのクラス(仕組み)です。
「新しいクエリを自分で作って、好きな条件で投稿を表示したい」ときに使います。

主な特徴まとめ

特徴内容
🔸 新しいクエリを作れるメインループとは別に、任意の条件で投稿を取得できる。
🔸 柔軟な条件指定が可能投稿タイプ・カテゴリー・タグ・並び順・メタ情報など、細かく設定可能。
🔸 ループ制御が必要取得結果を while ループで回して出力する必要がある。
🔸 メインクエリを壊さないquery_posts() と違い、WordPressの標準動作に影響を与えない。

つまり、安全にサブクエリを扱える柔軟な方法WP_Query() です。

基本構文

$args = array(
  'post_type'      => 'post',      // 投稿タイプ(投稿、固定ページ、カスタム投稿など)
  'posts_per_page' => 3,           // 表示件数
  'orderby'        => 'date',      // 並び替え基準
  'order'          => 'DESC',      // 昇順 or 降順
  'category_name'  => 'news',      // 特定のカテゴリを指定
);

$the_query = new WP_Query($args);   // クエリを作成

if ( $the_query->have_posts() ) :   // 投稿があるかチェック
  while ( $the_query->have_posts() ) : $the_query->the_post();
    the_title('<h2>', '</h2>');
    the_excerpt();
  endwhile;
  wp_reset_postdata();              // グローバル変数を元に戻す(重要)
endif;

各部分の説明

部分役割
$args取得条件を配列で指定。カテゴリーや件数などを細かく設定できる。
new WP_Query($args)条件に合う投稿を取得するオブジェクトを生成。
have_posts() / the_post()ループ処理を行うためのメソッド。
wp_reset_postdata()メインクエリに戻すための関数。これを忘れると次のループで不具合が起きる。

よくある使用シーン

シーンコード例
最新の投稿3件を表示'posts_per_page' => 3
「お知らせ」カテゴリのみ取得'category_name' => 'news'
カスタム投稿タイプ「works」から表示'post_type' => 'works'
タグ「design」を含む投稿'tag' => 'design'

メリット・デメリット

項目メリットデメリット
柔軟性取得条件を細かく設定できるループ処理がやや長くなる
安全性メインクエリを壊さないコード量が増える場合あり
拡張性カスタム投稿やメタ情報も簡単に指定可PHP初心者には少し複雑に感じる

ワンポイント

WP_Query() は、「メインループ(投稿一覧)」とは別に投稿を表示したいときに使うのが基本です。

  • トップページの下部に「最新のお知らせ」だけを出したい
  • サイドバーに「人気記事」一覧を表示したい
  • カスタム投稿タイプ(例:制作実績)を表示したい

といったケースでは、WP_Query() が最も使われます。

get_posts()の特徴と注意点

get_posts() は、WP_Query を簡易的にラップした関数で、軽量に投稿リストを取得したいときに使われます。
たとえば「最新3件だけをサイドバーに出す」など、単純な一覧表示に最適な関数です。

WP_Query よりも機能が省略されているので、設定や挙動を正しく理解しておかないと意図しない結果になることもあります。

ここでは、よくある失敗を踏まえて解説します。

デフォルトで ignore_sticky_posts = true

get_posts() は内部的に WP_Query を使っていますが、デフォルトで ignore_sticky_poststrue(= 固定表示を無視)に設定されています。

そのため、トップページなどで「先頭に固定表示」にした投稿を取得したい場合、get_posts() を使うと除外されてしまうことがあります。

📌 対処法として、以下のように明示的に ignore_sticky_posts => false を指定します。

$args = array(
  'posts_per_page'      => 5,
  'ignore_sticky_posts' => false, // 固定表示も含める
);
$posts = get_posts($args);

この1行を入れるだけで、sticky 設定された投稿も取得対象になります。

シンプルだが柔軟性に欠ける

get_posts() の特徴は「軽くて速い」こと。
ただしその分、取得条件や制御が制限される点には注意が必要です。

項目WP_Queryget_posts
柔軟な条件指定◎ 可能(複雑な条件もOK)△ 一部のみ対応
ページング(ページ送り)◎ 対応× 対応していない
投稿数制御◎ posts_per_pageで指定○ posts_per_pageで指定可能
固定表示投稿デフォルトで反映デフォルトで無視(要設定)
メインクエリとの干渉なしなし(安全)

つまり、get_posts() は「一覧を軽く出したいとき専用」。
ページネーションや検索結果表示のような複雑なクエリには向きません。

ループ内で the_post() を使う場合の注意

get_posts() は投稿データの配列を返すため、WP_Query のように自動で $post グローバル変数を更新しません。

そのまま the_title()the_content() を使うと、正しい投稿情報が出力されないことがあります。

📍正しい書き方は以下のようになります。

$posts = get_posts(array(
  'posts_per_page' => 3
));

foreach ($posts as $post) :
  setup_postdata($post); // グローバル変数にセット
  ?>
  <h2><?php the_title(); ?></h2>
  <p><?php the_excerpt(); ?></p>
<?php
endforeach;
wp_reset_postdata(); // 元に戻す

setup_postdata() を呼ぶことで、
the_title()the_permalink() などのテンプレートタグが正しく動作します。

get_posts()のまとめ:軽量な用途と制約

向いているケース向いていないケース
サイドバーの最新投稿リストページネーションを伴う一覧
固定数の関連記事表示検索結果・アーカイブページ
カスタム投稿を数件だけ取得複雑な条件を組み合わせたいとき

get_posts() は「軽くてシンプル」。
ただし、「固定表示投稿を含めたい」「ページ送りをしたい」場合には、WP_Query() を選ぶのが確実です。

3つの関数の使い分け早見表

WordPressで投稿を取得する主な関数は、「query_posts()」「WP_Query」「get_posts()」の3つです。
目的によって最適な使い分けがあるので、以下の表を参考に、状況に応じて正しい関数を選びましょう。

用途最適な関数補足
メインクエリを条件変更したいpre_get_postsquery_posts() は使わない
サブループで一覧を出したいWP_Query投稿一覧・カスタム投稿などに最適
固定ページ内で特定記事だけ出したいget_posts軽量処理に向く・ページング非対応
ポイント
  • query_posts() はメインクエリを上書きしてしまうため、テーマやプラグインとの競合を起こすリスクがあります。
  • 一般的には、サブループを作る場合は WP_Query、軽量に数件だけ取得したいときは get_posts、既存クエリを変更したい場合は pre_get_posts を使うのがベストです。

実践例|同じ条件で3つの方法を比較

では実際に、「最新の投稿を3件だけ表示する」という同じ条件を、3つの方法で書き比べてみましょう。

コードの見た目や動作の違いがわかりやすくなります。

1.query_posts() の場合(非推奨)

<?php
query_posts(array(
  'posts_per_page' => 3,
));

if (have_posts()) :
  while (have_posts()) : the_post();
    the_title();
  endwhile;
endif;

wp_reset_query();
?>
注意点

query_posts() はメインクエリを直接上書きします。
プラグインやページネーションとの競合が起きやすく、公式ドキュメントでも非推奨とされています。

2.WP_Query の場合(推奨)

<?php
$args = array(
  'posts_per_page' => 3,
);
$query = new WP_Query($args);

if ($query->have_posts()) :
  while ($query->have_posts()) : $query->the_post();
    the_title();
  endwhile;
endif;

wp_reset_postdata();
?>
特徴
  • メインクエリを壊さず、サブループとして安全に使える
  • カスタム投稿タイプや複雑な条件にも対応できる
  • 実務でも最も一般的な方法です

3.get_posts() の場合(軽量)

<?php
$args = array(
  'posts_per_page' => 3,
  'ignore_sticky_posts' => false, // 固定表示を含めたい場合
);
$posts = get_posts($args);

foreach ($posts as $post) :
  setup_postdata($post);
  the_title();
endforeach;

wp_reset_postdata();
?>
特徴
  • 軽量で、配列として投稿データを返す
  • ページネーション非対応
  • サイドバーやウィジェットなど、ちょっとした一覧出力に最適

まとめ|正しく使い分けてトラブルを防ごう

WordPressの投稿取得は、一見似たような関数でも挙動が大きく異なります。
間違った関数を使うと、意図しない表示や不具合の原因になることも。

以下を押さえておけば安心です👇

  • query_posts() は基本使わない(非推奨)
  • WP_Query() は汎用的で安全(メインでもサブでもOK)
  • get_posts() は軽量だが制約あり(簡易用途向け)
  • pre_get_posts を使えばテーマ改修に強い(条件変更を安全に実装可能)

正しい関数を選べば、テーマの保守性やSEOにもプラスに働きます。
特に実務では、WP_Query+pre_get_posts の組み合わせが最も安心です。

この記事を書いた人
管理人

2012年にWebデザインの勉強を始め、2013年より制作会社に勤務。
これまでに500件以上のWebサイト制作・運用に携わってきました。
現在も制作会社に勤務しながら、Webデザインスクールのトレーナーとしても後進の育成に取り組んでいます。
WordPressやデザインの実践的なノウハウを、初心者にもわかりやすく発信できるよう試行錯誤しています。

管理人をフォローする
WordPress
スポンサーリンク
管理人をフォローする

コメント

タイトルとURLをコピーしました