いつも使っているwordpressのメインループとサブループ。
なんとなく理解しているつもりでしたが、いろいろ調べていくうちに意外に知らないことがあったので、整理してみました。
目次
- 1. メインループとは
- 1-1. グローバル変数$wp_queryと$post
- 1-2. メインクエリのデータ取得条件を変更する
- 2. サブループとは
- 2-1. WP_Queryのコード例
- 2-2. get_postsのコード例
- 2-3. query_postsは非推奨
- 3. まとめ
メインループとは
まず、メインループのコードから。
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<!-- ループ処理(例) -->
<a href="<?php the_permalink() ?>"><?php the_title(); ?></a>
<?php endwhile; endif; ?>
メインループの各コードの意味。
if (have_posts()): 記事が存在するかチェック
while (have_posts()): 記事がある間は、処理を繰り返す
the_post() 次の記事情報を取得する
※the_permalink()、the_title()はテンプレートタグと呼ばれる、the_post()を前提とする処理。
本筋からそれるのでここでは割愛します。
下記テンプレートにメインループを記載した場合、デフォルトの「投稿」記事一覧が表示されます。
index.php、archive.php (※カスタム投稿なしの場合)
コードの意味を見ても分かるとおり、メインループ自体は、あくまで取得したデータを出力するための繰り返し処理です。
ではデータはいつ取得しているのかというと、テンプレートを読み込む前です。
wordpressは、リクエストされたURLによって取得するデータを判別し、データ取得後にテンプレートを表示する仕組みです。
この事前にデータを取得する命令文のことをメインクエリと呼びます。(クエリ:問い合わせ)
クエリはSQLというデータベースを操作する言語で記載され、データベースに対して実行します。
wordpress内部処理のイメージ
URL: http://sample.com/
2.URLからメインクエリを特定し、データベースからデータを取得する。
メインクエリ: "デフォルトの「投稿」データを取得しなさい"(SQL文)
3.URLから読み込むテンプレートを決定する。
wordpressの内部命令: "index.phpを読み込め"
4.テンプレートを読み込む
index.phpの読み込み
参考:WordPress Codex(日本語版) クエリ概要
メインクエリ特定部分は上記URLの「WP->parse_request()の詳細」を参照してください。
まとめるとメインループとは、
メインクエリで取得したデータを、テンプレート内で出力するための繰り返し処理です。
対応するメインクエリのデータ以外のデータが欲しい場合に必要になってくるのがサブクエリ&サブループです。
「index.phpでカスタム投稿タイプxxxのデータを取得したい」など。
サブループについては後ほど解説します。
グローバル変数$wp_queryと$post
wordpress内部の話。
メインクエリで取得したデータは、グローバル変数$wp_queryに格納されます。
ループ処理のhave_posts()は、$wp_queryに対してデータが存在するかチェックする関数。
the_post()は$wp_queryから順にデータを取り出し$postに格納する関数です。
※グローバル変数とは
どのファイルからもアクセス可能な変数のこと。
wordpress固有のものではなく、プログラミング言語共通の用語です。
wordpressは他にも多くのグローバル変数を持っています。
下記コードをテンプレートのメインループ外に記載すると、$wp_queryの中身が確認できます。
<?php var_dump($wp_query); //中身確認 ?>
各投稿データごとに確認したい場合は、メインループ内に下記コードを記載することで$postの中身が確認できます。
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<?php var_dump($post); //中身確認 ?>
<?php endwhile; endif; ?>
これを知っておけば、テンプレートごとに(メインクエリによって)どのようなデータが取得できるか確認することができます。
メインクエリのデータ取得条件を変更する
メインクエリで取得するデータは、テンプレートを読み込む前に決定されるので、取得したいデータの条件を変更する場合はfunctions.phpに記載する必要があります。
(funcsions.phpはメインクエリ実行前に読み込まれる)
functions.php記載例
function my_custom_query_vars( $query ) {
if ( !is_admin() && $query->is_main_query()) {
if ( is_post_type_archive('news') ) {
$query->set( 'posts_per_page' , 3 );
}
}
return $query;
}
add_action( 'pre_get_posts', 'my_custom_query_vars' );
上記はカスタム投稿タイプnewsの表示件数を3に設定する例です。
pre_get_posts関数に対してアクションフックを設定しています。
重要なポイントは
if ( !is_admin() && $query->is_main_query()) {の部分。
「管理者画面ではない」かつ「メインクエリ」である場合のみ、処理を設定するという意味です。
pre_get_postsはいたるところで使われる関数なので、上記処理を入れないと思わぬ箇所で設定が効いてしまうことがあります。必ず記載すること。
サブループとは
メインループの説明で、メインクエリという用語ができたように、サブループにもサブクエリという概念が存在します。
サブクエリとは、メインクエリで取得するデータとは別のデータを取得するための、自分で作るクエリのことです。
もう言わなくてもわかるかと思いますが、サブループとは、サブクエリで取得したデータを出力するための繰り返し処理です。
index.phpでカスタム投稿newsのデータを取得したい場合の、サブクエリ&サブループのコード例。
<?php
$my_query = new WP_Query();
$args = array(
'post_type' => 'news',
);
$my_query->query( $args ); //データ取得
?>
<?php if( $my_query->have_posts() ): while( $my_query->have_posts() ) : $my_query->the_post();?>
//サブループ処理
<a href="<?php the_permalink() ?>"><?php the_title(); ?></a>
<?php endwhile; endif; wp_reset_postdata(); ?>
$my_query->query( $args );で、$argsの情報をwordpress内部で受け取り、SQL文を生成します。(サブクエリ)
サブクエリをデータベースに対して実行し、取得したデータが$my_queryに格納されます。
サブクエリの作成方法は、WP_Queryとget_postsの、2種類方法があります。
違いはいくつかありますが、自分が欲しいデータが取得できるならどっちを使っても良し。
サブループの注意点
サブループの終わりには必ずwp_reset_postdata();を記載すること。
サブループの$my_query->the_post();処理は、グローバル変数$postを上書きしてしまうため、リセットする必要があります。
WP_Queryのコード例
<?php
$my_query = new WP_Query();
$args = array(
'post_type' => 'news',
);
$my_query->query( $args );
?>
<?php if( $my_query->have_posts() ): while( $my_query->have_posts() ) : $my_query->the_post();?>
<a href="<?php the_permalink() ?>"><?php the_title(); ?></a>
<?php endwhile; endif; wp_reset_postdata(); ?>
get_postsのコード例
<?php
$args = array(
'post_type' => 'news'
);
$posts_array = get_posts( $args );
?>
<?php foreach ( $posts_array as $post ) : setup_postdata( $post ); ?>
<a href="<?php the_permalink() ?>"><?php the_title(); ?></a>
<?php endforeach; wp_reset_postdata(); ?>
query_postsは非推奨
query_postsもサブクエリの一つでしたが、現在は非推奨となっています。
古い記事でたまに見かけるので、一応書いておきます。
メインクエリに影響を与える処理なので、絶対に使わないように。
まとめ
メインループ
メインクエリで取得したデータを出力するための繰り返し処理。
サブループ
サブクエリで取得したデータを出力するための繰り返し処理。
メインクエリとサブクエリの相違点はこちら。
メインクエリ | サブクエリ | |
---|---|---|
処理の実装 | wordpressが事前に用意しているため必要なし。 条件変更はpre_get_posts使う。 |
自分で作成。 WP_Queryかget_postsを使う。 |
処理の実行タイミング | テンプレート読み込み前に実行 | テンプレート読み込み後(テンプレート内で)実行 |
処理の実行回数 | 1テンプレートにつき1回だけ | 作ったサブクエリ分だけ何回でも |