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 の違いが曖昧…」そんなモヤモヤを一気にクリアにします!