WordPressで投稿を取得する方法といえば、get_posts() か WP_Query。
この記事では「どちらを使えばいいのか」「失敗しない使い分け方」を初心者にもわかりやすく解説します。
get_posts()とWP_Query、どちらが正解なのか? 実は、それぞれ役割がまったく違うんです。
✅ 今回のゴール
よくある失敗や注意点まで学び、実案件に活かせる力をつける
get_posts() と WP_Query の違いを理解する
シンプルな一覧取得/複雑な条件分岐の使い分けができるようになる
「投稿を一覧で表示したい」その時、どっちを使う?
WordPressでよくあるお悩み:
- 「最新記事をサイドバーに出したい…」
- 「カテゴリで絞り込んだ一覧を作りたい…」
- 「カスタム投稿を条件付きでループしたい…」
そんなときに使えるのが、get_posts() と WP_Query の2つの投稿取得手段です。
ただしこの2つ、向き不向きがハッキリしてるのが要注意!
今回は、WordPressで「投稿一覧を出したい」ときによく使う get_posts() と WP_Query の違いを整理し、それぞれの使いどころをわかりやすく紹介していきます!
「WordPress 投稿取得の基本をおさえたい」という方にピッタリの内容です。
1. get_posts() の特徴
🧩 シンプルな投稿取得
WordPressで最も手軽に投稿を取得できるのが get_posts()。サッと投稿を数件だけ取りたい時にピッタリです。
取得結果は「投稿オブジェクトの配列」で返ってきます。
<?php
// 最新の通常投稿(post)を5件、日付の新しい順で取得
$latest_posts = get_posts([
'posts_per_page' => 5,
'post_type' => 'post',
'orderby' => 'date',
'order' => 'DESC',
]);
// 各投稿に対してループ処理を行う
foreach ($latest_posts as $post) :
// 投稿データを WordPress のグローバル変数に設定(テンプレートタグが使えるように)
setup_postdata($post);
?>
<li><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></li>
<?php
endforeach;
// 投稿データの状態を元に戻す(ループ後は毎回必要)
wp_reset_postdata();
?>💡 注意点
query_posts()と違ってメインループを壊さない- ページネーションには対応していない
- ループ状態を操作するには
setup_postdata()とwp_reset_postdata()が必要
👉 軽量・高速だが、機能はシンプル。
一覧ページよりも サイドバーやフッター向け。
📌 ページネーションや複雑な条件での絞り込みが必要な場合は WP_Query に切り替えましょう。
※補足:実は get_posts() は内部的に WP_Query を呼び出しています。つまり「簡易版WP_Query」とも言えますが、機能が制限されているぶん、軽量で高速です。
2. WP_Query の特徴
🔍 柔軟で多機能、なんでも対応
WordPressで複雑な条件で投稿を取得したいなら、やはり WP_Query の出番。投稿タイプやカスタムフィールドを組み合わせた絞り込みも得意です。
カスタム投稿、タクソノミー、メタ情報など複雑な条件でも対応可能です。
<?php
// 投稿タイプ「news」から、カスタムフィールド「important」が「1」の投稿を10件取得
$args = [
'post_type' => 'news',
'posts_per_page' => 10,
'meta_key' => 'important', // 絞り込み対象のカスタムフィールド
'meta_value' => '1' // 「1」の投稿のみ対象
];
// WP_Query のインスタンスを作成
$news_query = new WP_Query($args);
// 投稿が存在する場合にループ処理を開始
if ($news_query->have_posts()) :
while ($news_query->have_posts()) :
$news_query->the_post(); // 投稿データを1件分取得
?>
<article><h2><?php the_title(); ?></h2></article>
<?php
endwhile;
// 投稿データの状態をリセット(メインクエリに戻す)
wp_reset_postdata();
endif;
?>💡 注意点
- 書き方がやや長め
- 複雑な条件ではデータベース負荷が増える
- ページネーションも制御できる(
max_num_pagesなど)
👉 強力だが、慎重に使う必要あり。
3. 使い分けの目安
| 使用ケース | 推奨 |
|---|---|
| サイドバーで「最新投稿」を数件表示したい | ✅ get_posts() |
| ページ送り付きの一覧ページを作りたい | ✅ WP_Query |
| カスタム投稿・カスタムフィールドを使う | ✅ WP_Query |
| 数件だけ取得して処理したい(軽量) | ✅ get_posts() |
💡get_posts() と WP_Query の使い分けに迷ったら、このルールを思い出しましょう:
- 「軽い・少ない → get_posts()」
- 「複雑・多い → WP_Query」
🪄 あえてさらに深掘るなら…
🔸 pre_get_posts フィルターで全体を制御
たとえば、トップページで特定カテゴリを除外したい場合:
// トップページの投稿一覧から、カテゴリID「5」の記事を除外
function modify_home_query($query) {
// 管理画面 or メインクエリ以外は処理しない
if (is_admin() || !$query->is_main_query()) return;
// フロント側トップページに対してのみ適用
if ($query->is_home()) {
$query->set('cat', '-5'); // マイナス値でカテゴリ除外
}
}
add_action('pre_get_posts', 'modify_home_query');⚠️ よくある失敗
is_main_query()を忘れると管理画面や他のクエリに影響して大事故に- 管理画面だけ除外したいときは
is_admin()を必ず併用
// 「event」投稿タイプのアーカイブページを「event_date」フィールドの昇順で並び替え
function modify_event_archive($query) {
if (!is_admin() && $query->is_post_type_archive('event') && $query->is_main_query()) {
$query->set('orderby', 'meta_value'); // カスタムフィールドの値でソート
$query->set('meta_key', 'event_date'); // 対象となる日付フィールド
$query->set('order', 'ASC'); // 昇順(古い順)
}
}
add_action('pre_get_posts', 'modify_event_archive');💡 さらに応用すれば、カスタム投稿のアーカイブ表示も自由自在に制御できます:
🔸 WP_Query を JSON形式で返す応用例
▼ 例:独自 REST API エンドポイントで WP_Query を返す
// 独自REST APIエンドポイント(/wp-json/custom/v1/events/)を登録
add_action('rest_api_init', function() {
register_rest_route('custom/v1', '/events/', [
'methods' => 'GET',
'callback' => 'get_custom_events',
]);
});
function get_custom_events() {
// 投稿タイプ「event」から5件取得
$query = new WP_Query([
'post_type' => 'event',
'posts_per_page' => 5,
]);
$results = [];
while ($query->have_posts()) {
$query->the_post();
// タイトルとリンクを整形して配列に追加
$results[] = [
'title' => get_the_title(),
'link' => get_permalink(),
];
}
wp_reset_postdata();
// 結果をJSON形式で返す
return rest_ensure_response($results);
}このコードを入れると、/wp-json/custom/v1/events/ にアクセスしたときに「イベント投稿5件」がJSONで返るようになります。
これを JavaScript の fetch() などで取得して、表示に使うことも可能です。
💡 応答に日付やカスタムフィールドを含めたい場合は、get_the_date() や get_field() を追加するだけでOKです。
💬 よくある質問(Q&A)
Q. get_posts() でページ送りできますか?
→ できません。ページネーション対応は WP_Query 一択です。
Q. WP_Query は重いの?
→ 条件が多くなるとクエリも重くなります。
fields => 'ids' でIDだけ取得する軽量化テクも有効です。
Q. query_posts() はもう使わないの?
→ 原則非推奨。メインクエリを壊してしまうため、今後は避けるべきです。
Q. 複数ループでうまく動かない…?
→ the_post() の連続呼び出しや wp_reset_postdata() の入れ忘れが原因かも。
ループの切り替え後は必ず状態を戻しましょう。
📝 まとめ
- 🔹 WordPressで投稿を取得するなら、
get_posts()は「軽量」「すばやく数件だけ取得」に最適
一方で、柔軟に条件を加えたい場合はWP_Queryの出番です - 🔹
WP_Queryは「複雑な絞り込み」「ページネーション」「カスタム投稿」に対応 - 🔹
pre_get_postsを使えば グローバルな制御 も可能 - 🔹
is_main_query()の有無やwp_reset_postdata()の使い方に注意!
📝 次回予告:「固定ページと投稿ページの違い・テンプレート階層を深掘り!」
次回は、page.php と single.php の違い、テンプレート階層のルール、条件分岐の仕組みなど、WordPressの裏側ロジックを紐解いていきます!
「テンプレート階層って何?」「page.php と single.php の違いが曖昧…」そんなモヤモヤを一気にクリアにします!
