メインループとサブループの違いは?

メインループとサブループの違いは?

WordPressの投稿記事の一覧などはメインループやサブループなどを使って表示させます。どれがメインループ?何がサブループ?カスタマイズ経験が浅いとよく理解できないまま混在してコードを書いてしまいがちです。
メインとサブをしっかり理解して使い分けることができれば、ページを表示させるときに無駄なクエリを減らして負荷を軽くすることが可能です。より効率的でスマートなテーマ作成を目指しましょう。

※ちなみに、説明するサイトによってはメインクエリやサブクエリといった表現がされる場合もあります。

厳密にいえば、「クエリ=読み込み」、「ループ=while文のループ」になるのでしょうが、そういった事も含めてメインループ、サブループで書き出す(出力する)などといった表現を行います。

メインループとは?

メインループとはテンプレートに対してデフォルトで読み込んで来てくれるクエリのことを言います。テンプレートが読み込まれる前に読み込まれていますが、functions.phpで制御できることを考えると、functions.phpの後に読み込まれているようです。

トップページのテンプレートindex.phpやfront-page.phpなどに対しては特に設定しなくてもデフォルトで「投稿」の情報を読み込んで来てくれます。という事で、トップページのメインループは「投稿」になります。そしてメインループを使って表示させるコードは下記になります。

if( have_posts() ) {
	echo '<ul class="newsList">';
	while( have_posts() ) {
		the_post();
		echo '<li><span class="date">' . get_the_time('Y年m月d日') . '</span><a href="' . the_permalink() . '">' . get_the_title() . '</a></li>';
	}
	echo '</ul>';
}

have_posts()でクエリの確認をして、クエリが存在すればwhile文でループしつつすべての情報を吐き出します。ulやliは任意で変えていただいて大丈夫です。

サブループとは?

サブループはメインループと違い自身で読み込む設定を行います。

例えば、「投稿」はトップページのテンプレートやarchive.phpなどにはデフォルトで読み込まれますが、固定ページのpage.phpには読み込まれません。
しかし、意図的に固定ページにお知らせの一覧を表示させたい場合もあると思います。page.phpがデフォルトで読み込むクエリは固定ページの情報ですので「投稿」の情報が欲しいときはサブループを使用します。
サブループのサンプルコードは下記になります。

//取得情報の指定
$args = array(
	'post_type' => 'post', //投稿タイプ
	'posts_per_page' => 5, //表示件数
	'orderby' => 'date', //並び順の参考情報(日付)
	'order' => 'DESC' //並び順の指定(降順)
);
//指定した情報をセット
$the_query = new WP_Query( $args );

if( $the_query->have_posts() ) {
	echo '<ul class="newsList">';
	while( $the_query->have_posts() ) {
		the_post();
		echo '<li><span class="date">' . get_the_time('Y年m月d日') . '</span><a href="' . the_permalink() . '">' . get_the_title() . '</a></li>';
	}
	echo '</ul>';
}
wp_reset_query(); //WP_Queryをリセット

コードの書き方はメインループに似ていますが、$argsで取得する情報を指定しWP_Queryにセットするところがサブループの特徴です。

一つのページに複数のサブループを使うこともあります。情報が混在して不具合を起こさない為にも一つのサブループが完了するごとにwp_reset_query()を使って情報をリセットしておきましょう。

ここでは取り上げませんが、$argsでセットする指定は上記以外にも多数存在し細かく取得情報を指定できます。

メインループの使いどころ

サブループでは指定によっては「投稿」を含めあらゆる情報を取得できますのでサブループだけ使ってればいいんじゃんって思ってしまいます。
正直私もサブループばかり使っている時期がありました。しかし、考えてください。メインループはサブループを使っても使わなくても読み込まれます。メインループで情報が読み込まれているにも関わらずわざわざ同じ情報をサブループで取得するのはクエリの無駄遣いになります。少しでもクエリを軽くするためにもクエリの重複は避けたいところです。

テンプレートでメインループを考える

まず記事の一覧ページを作りたい場合、archive.phpのテンプレートを使えば「投稿」の記事情報をメインループで取得することが可能です。

ではカスタム投稿タイプでお客様の声( voice )を作成した場合、その情報を読み込むには?

WP_Queryにセットする$argsで「’post_type’ => ‘voice’,」として情報を取得することも可能ですが、archive-voice.phpのテンプレートを使うことによってカスタム投稿タイプ(voice)をメインループとして取得することができます。

使用しているテンプレートがそのまま必要としている情報をメインループで取得できるのであれば利用しない手はありません。
とはいえテンプレートに関係なく情報が必要になる場合もありますのでその時は遠慮なくサブループを使いましょう。

メインループのクエリ指定

サブループは$argsに取得したい情報を細かく指定することができます。しかしメインループはすでに情報を取得してきますのでテンプレート上でどうこうすることができません。しかしメインループで情報の制御ができないわけではありません。メインループの情報はfunctions.phpで可能です。

/*-----------------------------------
 メインループのクエリ指定
-----------------------------------*/
function pickup_sort( $query ) {
	//管理画面を除外
	if ( is_admin() || ! $query->is_main_query() ) {
		return;
	}
	//ページ指定
	if ( $query->is_front_page() ) { //トップページ
		$query->set( 'posts_per_page', -1 );
	} elseif ( $query->is_post_type_archive('voice') ) { //お客様の声
		$query->set( 'posts_per_page', -1 );
		$query->set( 'orderby', 'date' );
		$query->set( 'order', 'DESC' );
	}
}
add_action( 'pre_get_posts', 'pickup_sort' );

上記コードは、トップページやお客さの声などページによって取得する情報を指定してます。管理画面でもフックされてしまいますので、管理画面での除外設定も忘れずにいれておきましょう。
$query->set();に入れる指定は$argsと同じです。

query_postsは使わない

私がカスタマイズを始めたころに参考にしていた本にはquery_postsでクエリを取得して一覧情報などを表示させていました。しかしまもなquery_postsは非推奨となりました。
古い記事でたまにquery_postsを使ったコードが残っていますが、現在はサポートされていませんのでWP_Queryを使うようにしましょう。

以上メインループとサブループの違いと使いどころを紹介させていただきました。

一覧表示のコードをどこからか見つけてきてコピペでコードを流用し、メインループなのかサブループなのか良く分からず使っていた方もこの記事で少しでも理解を深めていただければと思います。