イメージ

2024/03/22 コンテンツ・メーカー2のバージョン3.0を公開しました。

WordPressのメインクエリやメインループとは?サブとの違いは何か?


WordPressには「メインクエリ」や「サブクエリ」という用語・概念があります。
似たような言葉として「メインループ」とか「サブループ」というのも使われたりします。

それらがどのようなものかをあまり理解していなくても、特にトラブルが起きることなくWordPressサイトの制作ができる場合もあります。
が、ループに関する知識不足が原因で意図したとおりにページが表示されないことはよくあります。

きちんとWordPressサイトを作るためには「メインループ」や「サブループ」の理解を避けて通ることはできません。
ページが正しく表示されていても、これらをきちんと理解していないことが原因でサイトの表示速度が遅くなっている場合もあります。

今回はWordPressテーマの作成やカスタマイズをする際に避けては通れない「メインクエリ」や「メインループ」、「サブクエリ」や「サブループ」に関して解説します。

メインクエリやメインループとは何か?を正確に知るためには、まずWordPressがどのような処理をどのような順番で行っているかを大まかに知っておくと理解しやすくなります。

0、まず基本中の基本知識になりますが、WordPress本体(コアファイル)やプラグイン、テーマのファイルはWebサーバーに設置されています。
それに対し、WordPressの設定や記事のデータ(画像以外)はデータベースの方に記録されています。
WordPressの全体像
WordPress管理画面内の操作によってアップロードした画像ファイルも同じようにサーバー内にあります。(uploadsフォルダ)
これを知っておくと、バックアップやサーバーを移転する際に役に立つでしょう。

1、ページが表示される際には、まずクライアント(サイト閲覧者)のPC・ブラウザがURLによって表示したいページのリクエストを送る。
URLをリクエスト

2、するとWordPress本体(コアファイル)やプラグインファイルが読み込まれ、リクエストを受けたURLで表示するページ内容をデータベースに問い合わせます。
データベースに要求

3、データベースから記事データを受け取ると、WordPressはテーマ内のどのテンプレートファイルを使用するかを決定します。
テンプレートファイルの選択
この時、single.phpやpage.php、date.php、archive.phpなどのテンプレートファイルの中からどれが選択されるかは、上記手順1で受け取ったURLを元に決定されます。

補足説明:それぞれのテンプレートファイルには以下の図のように優先度が決められています。(画像の引用元:WordPress Codex 日本語版)
テンプレートの優先度

4、選択されたテンプレートファイルを読み込み、ページが表示されます。
この時、テンプレートファイル内や記事内で記述されている画像ファイルへの参照(img src=””)によって各画像も読み込まれます。(外部CSSファイルも同じ理屈)
ページの表示
参考サイト1:テンプレート階層 – WordPress Codex 日本語版
参考サイト2:クエリ概要 – WordPress Codex 日本語版

これまでの解説でわかるように、WordPressは最初にリクエストされたURLを元にデータベースから記事を呼び出します。
この時、データベースから呼び出される記事データが「メインクエリ」です。(厳密には呼び出す命令のことを指すかもしれません)

そして、それをテンプレートファイル内で表示するループが「メインループ」になります
説明だけだとわかりにくいので、具体例を挙げてみます。

例えば、最初にリクエストされたURLが「http://www.test.com/?p=1」であるなら、IDが1の投稿をデータベースから呼び出すことになります。
(パーマリンク設定に基づき、.htaccessのリライト機能によって別形式のURLから変換しているサイトが多いでしょう)
この「IDが1の投稿データ」がメインクエリとなります。

そしてこのデータが投稿ページに属するものであれば、テンプレートファイルはsingle.phpやsingular.phpあたりが優先度によって選択されることになります。
そのテンプレートファイル内で「IDが1の投稿データ」を表示させる際には、以下のようなコードを使うでしょう。

<?php
if ( have_posts() ): while ( have_posts() ): the_post();
  the_title();
  the_content();
endwhile; endif;
?>

上記コード内ではどの記事データを呼び出すかに関する記述がありません。
それなのに「IDが1の投稿データ」がきちんと表示されるのは、それがメインループだからです。

つまり、メインループおよびメインクエリが何になるかはテンプレートファイルが呼び出されるよりもっと前、URLの時点ですでに決まっているのです。

【補足】
「ループ」というと繰り返し何件も表示させるようなイメージがありますが、今回の例のようにたとえ1件しか表示されていなくてもループなのです。

「IDが1の投稿データ」は1件しか存在しないから1件の表示で終わっているだけで、上記コードをそのままcategory.phpやdate.phpなどに書けば複数件表示されることになるでしょう。

参考サイト:トピック: [解決済] 「メインループ」の定義は何ですか? « サポートフォーラム — WordPress

これまでの解説のとおり、URLの時点でメインクエリやメインループは決定されます。
しかしもし、投稿ページ内で固定ページ一覧を表示させたい場合はどうすればよいでしょうか?

その時にget_posts()関数などで呼び出すデータが「サブクエリ」、そしてそれを表示させるためのループが「サブループ」となります。

メインとサブの違いは何か?
上で解説したWordPressが行う処理の順序を見るとわかりますが、データベースから記事データを呼び出すのはテンプレートの選択よりも先に行われます
この時点でデータベースから呼び出したのがメインとなり、それ以外のものがサブとなります。

メインクエリを書き換える関数としてquery_posts()関数が有名ですが、テンプレートファイル内でこの関数を使用してメインクエリおよびメインループの内容を変更したとしても、その時にはすでに本来のメインクエリは読み込み終わってしまっています。

本来のメインクエリを読み込んだ後にquery_posts()関数によってメインクエリを上書きして再度読み込むのは、無駄なデータベースの読み込みが1回発生することになりますので、サイトの表示速度が遅くなります。

サイトの表示速度を下げないためには、本来のメインクエリが読み込まれる前の時点で読み込みたいメインクエリの指定をすべきでしょう。
そのような理由から、現在はメインクエリを変更するためにはpre_get_postsフックが推奨されています。

このフックはクエリ変数オブジェクトの生成後、実際にクエリが実行される前に呼び出されます。
プラグイン API/アクションフック一覧/pre get posts – WordPress Codex 日本語版


メインクエリはテンプレートファイルが選択される前に読み込まれていますから、不必要なデータベースの読み込みを発生させないために、適切なテンプレートファイルを使うことが望まれます。
例えば、

  • カテゴリ別アーカイブを表示させたいのに固定ページを使う。

というようなやり方はWordPressの仕様に反しています。
そのようなやり方をするとページネーション(ページ送り)が正しく実装できなかったり、ページの表示速度が遅くなったりする原因になります。

カテゴリ別アーカイブならcategory.phpやarchive.phpなどのテンプレートファイルを用意し、そのURLへリンクさせるのが正しいやり方となるでしょう。
そうすれば、ページネーションも簡単に実装できます。

WordPressの仕様に沿ったサイト設計(階層や親子関係など)をするためには、どのような種類のテンプレートファイルが用意されているかをCodexで確認した上で設計をする必要があります。

テンプレートファイルの一覧は以下のページで確認できます。
参考ページ:テンプレート階層 – WordPress Codex 日本語版

WordPressを使ったサイトを構築する際には必須の知識と言えるでしょう。

提供サポートなど