こんにちは!WordPressの裏側の仕組みを紐解くのは、本当にワクワクしますよね。他のプログラミング言語からやってくると、「WordPressって、なんでこんなに簡単に記事が取得できるんだろう?」と感動する反面、「なんだか最近、サイトの動作が重いな…」と壁にぶつかることも多いはずです。
今回は、プログラミング初学者や、他言語からWordPressの世界へ飛び込んできた開発者に向けて、「WP_Queryのメモリ消費を劇的に抑える極意」を一緒に学んでいきましょう。
ここをクリアすれば、WordPressのデータ構造の本質がグッと見えてきますよ。データベースに無駄な負荷をかけないスマートなコードを書けるようになって、ワンランク上のエンジニアを目指しましょう!
—
なぜデフォルトの `WP_Query` はメモリを食うのか?
まずは、WordPressの心臓部である `WP_Query` が裏側で何をしているのかを、イメージ図で覗いてみましょう。
通常、私たちが以下のようなコードを書くと……
// 普通のクエリ発行
$query = new WP_Query( array( ‘post_type’ => ‘post’ ) );
WordPressはデータベースから「記事のID」だけでなく、以下のような全データを一度にメモリ上にロードしようとします。
- タイトル (`post_title`)
- 本文 (`post_content`)
- 抜粋 (`post_excerpt`)
- カスタムフィールドのメタデータ
- その他の膨大なシステム情報(WP_Postオブジェクト全体)
これをプログラミングの比えで言うなら、「たった1個の商品の値段(ID)を確認したいだけなのに、倉庫から商品そのもの(巨大なダンボール箱)を何百個もトラックで自宅のリビングに運び込んでいる状態」です。
そりゃあ、表示スピードも遅くなるし、メモリ制限(Memory Limit)に引っかかってエラー(Fatal error: Allowed memory size exhausted)が起きてしまいますよね。
—
救世主 `fields => ‘ids’` の登場
そこで使ってほしいのが、今回本題となるパラメータ `’fields’ => ‘ids’` です。
これを使うと、WordPressに対して「記事の中身なんていらないから、データベースから『IDの数字の列』だけをシュッと取ってきて!」と命令できます。
実際のコードを見てみましょう。
/
$args = array(
‘post_type’ => ‘post’,
posts_per_page => 20,
‘fields’ => ‘ids’, // ★ここが魔法のパラメータ!
);
$post_ids_query = new WP_Query( $args );
// 取得できるのは WP_Post オブジェクトの配列ではなく、整数の配列 [ 105, 89, 42, 12 ]
$post_ids = $post_ids_query->posts;
if ( ! empty( $post_ids ) ) {
foreach ( $post_ids as $post_id ) {
// IDだけが手に入るので、必要なデータだけをピンポイントで処理できる
echo ‘処理中の記事ID: ‘ . esc_html( $post_id ) . ‘
‘;
}
}
たったこれだけの記述で、メモリ使用量を劇的に(場合によっては何分の1にも)削減できます。他の言語(Laravelの Eloquent で言う `pluck(‘id’)` や、素のSQLの `SELECT id FROM …`)を触ったことがある方なら、「なるほど、要はこれね!」とスッと腑に落ちたのではないでしょうか。
—
よくある落とし穴:初心者がハマる文法・設計エラー
「よし、じゃあこの `fields => ‘ids’` をあちこちで使おう!」と思ったあなた、ちょっと待ってくださいね。ここで、初学者が非常によくやってしまう「痛いミス」をいくつかご紹介します。
1. 取得したIDに対して、間違ったメソッドを使ってしまう
`fields => ‘ids’` を使うと、 `$query->posts` の中身は `WP_Post` オブジェクトではなく、ただの数字(ID)の配列になります。そのため、以下のようなコードを書くとエラーになります。
// 【NGな例】IDの配列に対して、オブジェクト用のプロパティを叩いちゃダメ!
foreach ( $post_ids as $post_id ) {
// $post_id は単なる「数字(例: 105)」なので、$post_id->post_title はエラーになる!
echo $post_id->post_title;
}
正しいアプローチ
もし記事のタイトルやURLを使いたい場合は、IDから必要な分だけ都度データを呼び出すか、テンプレートタグにIDを渡してあげます。
// 【OKな例】IDから必要な情報だけを表示する
foreach ( $post_ids as $post_id ) {
// テンプレートタグにIDを渡すことで、その都度安全にデータを取得できる
$title = get_the_title( $post_id );
$permalink = get_permalink( $post_id );
echo ‘‘ . esc_html( $title ) . ‘ج
‘;
}
2. 「すべてのデータを出力したい画面」で使ってしまう
もし、Webサイトのメインブログ一覧ページ(アーカイブページ)など、「すべての記事のタイトル、アイキャッチ画像、抜粋、投稿者名」を丸ごと表示する必要がある場所で `fields => ‘ids’` を使ってしまうとどうなるでしょうか?
結局、ループの中で1件ずつデータを取得するクエリ(N+1問題)が大量に走ってしまい、逆にデータベースへの負荷が増えてサイトが遅くなります。
- 使うべきシーン: ウィジェットでの最新記事のIDリスト取得、独自のキャッシュ処理、一括バッチ処理、関連IDの配列だけが欲しいとき。
- 使わないべきシーン: 標準のメインループや、1ページ分の全情報をそのままHTMLとしてレンダリングする場所。
適材適所で使い分けるのが、プロへの第一歩ですよ。
—
まとめ:ここをクリアすればWordPressの基本はバッチリ!
今回は、`WP_Query` のメモリ消費を抑える最強の武器 `fields => ‘ids’` について解説しました。
- デフォルトの `WP_Query` はオブジェクト全体を抱え込むためメモリを消費しやすい。
- `’fields’ => ‘ids’` を使えば、IDの配列だけを軽量に取得できる。
- 返り値がオブジェクトではなく「数値の配列」になる点に注意する。
- 用途に合わせて正しく使い分けることで、サーバーの負荷を劇的に軽減できる。
この概念が頭に入っていれば、大規模なWordPressサイト構築や、プラグイン開発に挑むときも怖くありません。データベースとメモリの動きを意識しながら、スマートで美しいコードを書いていきましょう。
あなたのWordPress開発ライフが、もっと楽しく快適になりますように!