追加する一覧か、今ある一覧かで選びます
固定ページや記事下へ別の投稿一覧を追加するなら、まずコード不要のQuery Loopを検討します。PHPが必要でも、数件を配列で受け取るだけならget_posts()、独自のループ・総件数・ページ数まで扱うならWP_Queryが候補です。
カテゴリー、検索、投稿タイプアーカイブなど、WordPressが用意した一覧の取得条件をPHPで変えるなら、pre_get_postsでメインクエリを対象にします。まず「今ある一覧を変えたいのか、もう1つ足したいのか」から考えてみましょう。
3つの質問から使う方法を絞る
作りたい一覧が思い浮かんでも、いきなり関数名から選ぶのは難しいものです。まずは置く場所と表示したいものを決め、次の質問を上から見てみましょう。候補が決まったら、その方法の説明へ進めます。
1. WordPressが用意した一覧の取得条件を変えたい?
はいなら、カテゴリーや検索などのメインクエリを変更するpre_get_postsが候補です。いいえで、ページの中へもう1つ一覧を追加したいなら、質問2へ進みます。なお、サイト全体の表示件数を変えるだけなら、WordPressの表示設定で足りる場合もあります。
2. エディターの設定だけで、必要な条件と見た目を作れる?
はいなら、Query Loopを選べます。いいえで、PHPを使った処理が必要なら質問3へ進みます。たとえば独自のカスタムフィールド条件や、取得後のデータ処理が必要な場合です。
3. 投稿やIDの配列だけを受け取れれば足りる?
はいなら、get_posts()が候補です。いいえで、テンプレートタグを使うループ、総件数、総ページ数まで扱いたいならWP_Queryを選びます。数件の表示でも、ループで書く方が分かりやすければWP_Queryで構いません。
実際の要望に当てはめると、次のように選べます。
| 今やりたいこと | 第一候補 | 選ぶ理由 |
|---|---|---|
| 固定ページへコードなしで記事一覧を置く | Query Loop | エディターで取得条件、繰り返す表示、ページ送りを組み立てられる |
| テンプレート内で最新記事を3件だけ取得する | get_posts() | 必要な数件を配列で受け取り、foreachで扱いやすい |
| 記事の下へ独自の条件で関連記事を出し、ループやページ情報も使う | WP_Query | オブジェクトに結果、総件数、総ページ数、ループの状態を持てる |
| カテゴリー一覧の表示件数を変える | pre_get_posts | WordPressが実行するメインクエリを取得前に調整できる |
4つの方法を変更対象・返り値・ページ送りで比べる
WP_Queryとget_posts()は、どちらも投稿を新たに取得できます。pre_get_postsは投稿一覧を返す関数ではなく、実行前のクエリを変更するフックです。Query Loopは、投稿の取得と繰り返す見た目をエディター上で組み合わせるブロックです。表の「受け取るもの」は、処理後にコードや画面で使える結果を表しています。
| 方法 | 主な変更対象 | 受け取るもの | ページ送り | 主な置き場所 |
|---|---|---|---|---|
| Query Loop | ページ内へ追加する一覧 | ブロックが表示まで担当 | ページ送りブロックを追加できる | 投稿・固定ページ・ブロックテンプレートのエディター |
| get_posts() | 追加で使う数件の投稿 | WP_PostまたはIDの配列 | 総件数・総ページ数の利用には向かない | PHPテンプレート、関数、プラグイン |
| WP_Query | 追加で取得する投稿 | WP_Queryオブジェクト | found_postsとmax_num_pagesを扱える | PHPテンプレート、テンプレートパーツ、プラグイン |
| pre_get_posts | これから実行するクエリ | 渡されたWP_Queryを変更 | メインクエリのページ送りと合わせて調整しやすい | functions.phpまたはサイト固有プラグイン |
Query Loopはブロックテンプレートで元のクエリを引き継ぐ使い方もできます。ここではページ内へ別の一覧を追加する場面を比べているため、表の説明をその用途へ絞っています。
コードの見た目も短く並べてみます。次は違いを読むための抜粋です。4つをまとめて貼り付ける完成コードではありません。 Query LoopはPHPの関数ではないため、エディターで行う設定をコメントで示しています。
引数や処理の一部分だけを示した例です。このまま単独で貼らず、テンプレート内のWP_Queryとループへ組み込んでください。
// Query Loop:エディターで投稿タイプ・件数3・表示するブロックを設定。 // get_posts():配列を受け取る。表示は別に書く。$posts = get_posts( [ 'posts_per_page' => 3 ] ); // WP_Query:オブジェクトを作る。表示ループは別に書く。$query = new WP_Query( [ 'posts_per_page' => 3 ] ); // pre_get_posts:これから実行するカテゴリーのメインクエリを変える。add_action( 'pre_get_posts', function ( WP_Query $query ) { if ( ! is_admin() && $query->is_main_query() && $query->is_category() ) { $query->set( 'posts_per_page', 3 ); }} );get_posts()とWP_Queryは取得部分だけならどちらも短く書けますが、受け取るものは配列とオブジェクトで異なります。pre_get_postsは条件を変える処理を先に登録する書き方です。行数より、取得した後に何を使いたいかで選ぶと迷いにくくなります。実際に置く場所と表示まで含めた例は、この先で分けて説明します。
Query Loopはコードを書かずに一覧を追加したいときに使う
固定ページへ新着記事、特定カテゴリーの記事、ポートフォリオなどを置きたい場合は、まずQuery Loopで作れるか確認します。Query Loopの内側にはPost Templateがあり、その中へタイトル、アイキャッチ、抜粋、日付などを配置します。必要ならPaginationとNo Resultsも追加できます。
Query Loopが向いているのは、編集者がエディターで取得条件と見た目を管理したい場合です。テーマやWordPressが用意する設定の範囲で要件を満たせるなら、PHPファイルを編集する必要はありません。
現在のQuery Loopには、表示中の記事を除外する設定もあります。まずエディターの設定で足りるか確かめてみましょう。複数の独自の値を複雑な条件で組み合わせる、取得した投稿IDをほかの処理へ渡すなど、画面設定だけでは表現できない要件があるときにPHP側の方法を検討します。
get_postsは少数の投稿を配列で受け取りたいときに使う
get_posts()は、条件に合う投稿をWP_Postの配列として受け取ります。WordPress公式も、小さく単純なパラメーターで投稿配列を取得する用途を適切な場面として説明しています。
次の例は、検証環境のカテゴリー「お知らせ」(ID 2)に属する公開投稿を、新しい順に3件取得します。後のコード・表・画像も同じカテゴリーを使います。ご自身の環境ではcatのIDを置き換え、カテゴリーで絞らない場合はこの行を外してください。
子テーマのtemplate-parts/latest-posts.phpへ保存し、single.phpのメインループでthe_post()を呼んだ後にget_template_part( ‘template-parts/latest-posts’ );を1回記述すると、その場所へ一覧を追加できます。クラシックテーマで、パーツの保存と呼び出しを組み合わせる例です。
新規のPHPファイルなら先頭に<?phpを置き、既存のPHP内へ追加するときは開始タグを重ねません。呼び出す側の1行もPHPの内側へ記述します。各WP_Postを関数へ直接渡すので、テンプレートタグが参照する投稿データは切り替わりません。
クラシックテーマのテンプレート(またはテンプレートパーツ)で、一覧を表示したい位置に置く例です。投稿本文やfunctions.phpへ、そのまま貼るコードではありません。
$latest_posts = get_posts( [ 'post_type' => 'post', 'post_status' => 'publish', 'posts_per_page' => 3, 'cat' => 2, 'orderby' => 'date', 'order' => 'DESC', ]); if ( $latest_posts ) { echo '<ul>'; foreach ( $latest_posts as $latest_post ) { printf( '<li><a href="%1$s">%2$s</a></li>', esc_url( get_permalink( $latest_post ) ), esc_html( get_the_title( $latest_post ) ) ); } echo '</ul>';}get_posts()は内部でWP_Queryを使いますが、返すのはクエリオブジェクトではなく投稿またはIDの配列です。また、ignore_sticky_postsとno_found_rowsは関数内でtrueに設定されます。総件数や総ページ数を使う一覧より、取得した数件をそのまま利用する処理に向いています。
この例はsetup_postdata()を使わないため、リセットも不要です。配列の中身と既定値の違いはget_postsとWP_Queryの比較で詳しく説明しています。
投稿の取得コードを試すときは、本番と分けたWordPress環境で、件数と表示順が意図どおりか見ておくと安心です。検証や公開に使うサーバーをこれから用意する場合は、XserverのPHP対応やバックアップ条件も確認できます。
WP_Queryは独自ループとクエリ情報が必要なときに使う
WP_Queryは投稿取得を扱うクラスです。new WP_Query( $args )で作るオブジェクトは、取得した投稿だけでなく、取得件数、条件に合う総件数、総ページ数、ループの現在位置も持ちます。ループで表示したり、ページ送りを作ったりしたいときに役立ちます。
次は同じカテゴリーの最新3件を表示する別の実装です。最初のパーツを丸ごと置き換えて比べます。両方を残すと一覧が2回表示されるため、比較後は使う方だけ残してください。
クラシックテーマのテンプレート(またはテンプレートパーツ)で、一覧を表示したい位置に置く例です。投稿本文やfunctions.phpへ、そのまま貼るコードではありません。
$latest_query = new WP_Query( [ 'ignore_sticky_posts' => true, 'post_type' => 'post', 'post_status' => 'publish', 'posts_per_page' => 3, 'cat' => 2, 'orderby' => 'date', 'order' => 'DESC', ]); if ( $latest_query->have_posts() ) { echo '<ul>'; while ( $latest_query->have_posts() ) { $latest_query->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_postdata();$latest_query->have_posts()で次の投稿があるかを確かめ、$latest_query->the_post()でその投稿へ進みます。どちらも$latest_query->から始めることで、今回取得した同じクエリの結果を使っています。先頭固定投稿の優先はignore_sticky_posts=trueで無効にし、前のget_posts例と揃えています。
the_post()はテンプレートタグが参照する投稿データを一時的に切り替えます。ここではメインループから呼び出しているので、終了後にwp_reset_postdata()でメインループの投稿へ戻します。追加した別のループへ入れ子にする場合は、戻す対象が異なる点に注意が必要です。リセットの説明も参考にしてください。
カテゴリーや検索のテンプレート内でnew WP_Query()を作っても、元の一覧を取得するメインクエリは変わりません。今ある一覧そのものの条件を変えたい場合は、次のpre_get_postsを検討します。
WP_Queryを使う方法に決めたら、WP Query Builderで取得条件を組み立ててみましょう。今回のカテゴリー・3件・日付降順から始め、生成した$argsと表示コードを合わせて試せます。
使いたい投稿の条件を形にする
投稿タイプ・絞り込み・並び順・件数を画面で選べます。生成されたコードと説明を見比べ、設置場所やリセットはこの記事の例と合わせて実装します。
pre_get_postsは既存のメイン一覧を取得前に変えるときに使う
カテゴリー、タグ、検索結果、投稿タイプアーカイブなどは、WordPressがURLに合わせてメインクエリを準備します。この一覧の表示件数や対象投稿を変えるために、同じ一覧をnew WP_Query()で作り直す必要はありません。
pre_get_postsは、投稿を取得する前に処理を挟むためのアクションフックです。add_action()で関数を登録しておくと、WordPressがクエリを実行する前に呼び出します。
次の例は、公開側のカテゴリー一覧だけ表示件数を6件へ変えます。子テーマのfunctions.phpなど、クエリの実行前に読み込まれる場所のPHP開始タグの内側へ、関数とadd_action()をまとめて1回登録してください。比較用抜粋の3件設定とは併用しません。wptl_はサンプルの接頭辞なので、名前を変える場合はadd_action()の登録名も揃えます。
子テーマのfunctions.phpまたは機能プラグインに置く例です。対象画面と実行条件を確認し、検証環境で試してから本番へ反映してください。
function wptl_change_category_posts_per_page( WP_Query $query ) { if ( is_admin() || ! $query->is_main_query() ) { return; } if ( $query->is_category() ) { $query->set( 'posts_per_page', 6 ); }}add_action( 'pre_get_posts', 'wptl_change_category_posts_per_page' );この例では、is_admin()で管理画面を除外し、$query->is_main_query()でメインを選び、$query->is_category()でカテゴリー一覧に絞っています。検索や特定アーカイブを変える場合も、そのページに合う条件が必要です。
固定ページ1件を取得するメインクエリを、無理に投稿一覧へ変える用途には向きません。公式資料にも、単一ページとアーカイブのようにクエリの種類そのものを変える場合は、ページ種別を表す判定値の調整まで必要になる注意が書かれています。固定ページ内へ一覧を追加したいなら、Query Loop、get_posts()、WP_Queryから選びます。pre_get_postsとWP_Queryの使い分けでは、処理のタイミングも比べています。
同じ『最新3件』でも、置く場所で答えが変わる
よくある「最新3件」の要望を、置く場所まで含めて比べてみます。
「最新記事を3件表示したい」という要望だけでは方法を決められません。たとえば、固定ページの本文に3件のカードを足したいのか、カテゴリー一覧そのものを1ページ3件にしたいのかで、変える場所が違います。「どのページの、どこに表示するか」「今ある一覧を変えるのか、新しい枠を足すのか」まで書いてみると、使う方法を選びやすくなります。
| 要件を最後まで書いた例 | 選択 | 理由 |
|---|---|---|
| 固定ページの本文へ最新3件を、編集者が見た目を調整できるカードで追加 | Query Loop | 取得とカードの見た目をエディターで管理できる |
| テンプレートから最新3件のIDを受け取り、ほかの処理へ渡す | get_posts()+fields=ids | 表示ループやページ情報が不要で、配列を直接使える |
| 記事の下へ最新3件を追加し、テンプレートタグで表示 | WP_Query | 専用のループを持ち、the_post()でテンプレートタグを使える |
| 投稿一覧ページそのものをPHPで1ページ3件へ変更 | pre_get_posts | メインクエリのposts_per_pageを変える処理だから |
検索する時も「WordPress 最新記事 3件」だけでなく、「固定ページに追加」「カテゴリー一覧を変更」「ページネーションあり」「IDだけ取得」のように目的を足すと、合う方法を見つけやすくなります。
WP_Queryの取得条件をWP Query Builderで組み立てる
WP_Queryを使う方法に決めたら、投稿タイプ、絞り込み、並び順、表示件数をWP Query Builderで整理できます。今回のように通常投稿・3件・カテゴリーID 2・日付の新しい順を選び、生成した$argsを表示ループと合わせて使ってみましょう。
生成コードにはキャッシュや総件数の設定も含まれるため、本文の手書きコードとは値が異なることがあります。総ページ数も使うならno_found_rows=falseを確認します。Query Loopのブロック配置やpre_get_postsの対象判定は別に実装する部分です。
操作手順はWP Query Builderの使い方で説明しています。生成後は、置くテンプレート、表示HTML、エスケープ、リセットをこの記事の例と合わせて確認すると、取得から表示までつなげられます。
同じ投稿を4つの方法で扱って違いを確かめる
同じ「お知らせ」一覧を使い、3件を追加する場合と、今ある一覧を6件へ増やす場合を見比べてみましょう。WordPress 7.1/PHP 8.4.20のローカル環境で、カテゴリー「お知らせ」(ID 2)の公開投稿15件を対象にしています。新しい順の先頭3件は「メンテナンスのお知らせ」「春の更新情報」「確認用記事C」です。
get_postsとWP_Queryは、本文と同じ3件の条件です。pre_get_postsはカテゴリーのメインクエリ相当を作り、本文のフックで3件から6件へ変更します。Query Loopは投稿タイプpost・3件・日付降順・カテゴリーID 2・元のクエリを引き継がない設定で、WordPress標準のブロックを実際に描画します。先頭固定の優先は、追加する一覧の比較ではどれも無効にします。
| 確認項目 | 結果 |
|---|---|
| get_posts()で3件取得 | ID 13・10・63のWP_Post配列 |
| 同じ条件をWP_Queryで取得 | 同じ3件、総件数15、総ページ数5 |
| pre_get_postsでメインクエリを変更 | 3件から6件へ。別の追加クエリは3件のまま |
| Query Loopを実際に描画 | ID 13・10・63のタイトルをリンク付きで表示 |
まずはget_posts()の結果です。取得した配列から、3件のタイトルと内容を一覧へ表示しています。

取得したIDは13・10・63。配列から取り出した投稿を、サンプルサイトの一覧部品で表示しています。
WP_Queryでも、同じ条件なら見た目の3件は同じです。違うのは、総件数15・全5ページという情報も使える点です。

ID 13・10・63の3件は同じです。WP_Queryには総件数15・全5ページの情報もあります。ページ送り自体はこの画面には実装していません。
次はpre_get_postsで、もともとの一覧を6件へ増やした例です。先頭3件に「確認用記事B」「確認用記事A」「関連記事:画像を軽くする方法」が続きます。

ID 13・10・63に62・61・27が加わりました。変更したのはメイン一覧だけで、別に実行した追加クエリは3件のままです。
最後はQuery Loopです。PHPで表示用の一覧を書かず、投稿タイトルのブロックを繰り返して3件を表示しています。

ID 13・10・63のタイトルはWordPress標準ブロックの実出力です。共通のヘッダーとフッター内に配置しています。管理画面や本番環境の画面ではありません。
この結果は各方法の優劣ではなく、受け取れる情報と変更対象が異なることの確認です。実サイトでは投稿タイプ、公開状態、ユーザー権限、ページ送り、使用テーマを要件に合わせて再確認してください。
投稿一覧の方法を選ぶときによくある間違い
実装や公開へ進む前に、見落としやすい項目をまとめて確認します。
先に見直したい6項目
- Query Loopで足りる一覧でも、先にPHPファイルを編集する
- get_posts()から総ページ数を得ようとして、別の全件取得を追加する
- 既存アーカイブを変えたいのに、テンプレート内で同じ条件のnew WP_Query()を実行する
- pre_get_postsでメインクエリや画面を限定せず、管理画面や追加クエリまで変える
- WP_Queryの独自ループ後にwp_reset_postdata()を書かない
- 古いquery_posts()を見つけ、元の目的を確認せず別の方法へ置き換える
方法を変更する時は、取得条件まで同時に変えないでください。同じ投稿タイプ・件数・並び順で返り値と画面を比較し、置き換え後に条件を1つずつ足します。
WP_Query・get_posts()・pre_get_postsの公式資料
WP_Query、get_posts()、pre_get_posts、Query Loopで扱える範囲と、ページ数や既定値の違いは、次の公式資料で確認できます。
WordPress公式
確認に使った公式ドキュメント
変更対象と必要な情報から1つを選ぶ
方法が決まったら、少ない条件で同じ投稿が出ることから確かめます。0件・1件・複数件の表示、変更しない一覧への影響まで確認してから、本番へ反映してください。
本番へ反映する前の確認
- 必要な投稿・表示項目・ページ情報が揃っている
- 0件・1件・複数件で表示を確認した
- 管理画面や変更しない一覧に影響していない
- 追加ループ後の投稿データと、ページ送りを使う場合の2ページ目も正しい
- 比較用コードを残さず、問題時に変更を戻せる
この記事の検証情報
検証環境
- WordPress
- 7.1.4
- PHP
- 8.3.36
- テーマ
- wpq-media + DDEV
- 対象
- カスタム投稿 / taxonomy / meta_query
更新履歴
- 2026年10月27日 初回公開
この記事を活用する
あとで見返す・共有する
お気に入りに保存できます。役に立ったポイントは、いいねや共有で教えてください。






