WordPressでサイト制作をしているとメインの記事一覧以外に「別の記事一覧も出力したい!」となることが多々あります。
今回はそこで深く関係してくるメインループ、サブループ、WP_Queryについて解説をします。
- WordPressが記事一覧を出力する仕組み(メインループ)
- WordPressで「メインの記事一覧以外」にも記事一覧を出力する方法(サブループ)
- WP_Queryの使い方
- WP_Queryで使用可能なパラメータ一覧
WordPressが記事一覧を出力する仕組み(メインループ)
まずは大前提となる
そもそもWordPressがどうやって
「一覧ページ」や「個別ページ」などの記事情報を出力しているのか
という部分について簡単に解説をします。
WordPressではURLを元にデータベースから記事情報を自動取得している
WordPressでは、URL情報を元にデータベースから記事情報を取得して、それを各ページに出力する仕組みになっています。
具体的には以下のような流れで記事情報を取得→出力しています。
- ユーザーが何らかのページにアクセスする
- WordPressがURLを参照する
- URLの内容を元に「これは投稿ページか」「これはカテゴリーページか」などページ種別を判断する
- 判断した内容を元にデータベースから記事情報を取得する
※取得した情報はグルーバル変数に格納される - ④と同時に、ページの種類に応じたテンプレートファイル(front-page.phpやsingle.phpなど)を選択する
- ⑤で選択されたテンプレートファイル内に記述されているテンプレートタグ(the_title()など)によって記事情報が出力される
この記事をご覧になっている方は、恐らくテーマのカスタマイズやオリジナルテーマ制作など、何らかの形でWordPressのテンプレートファイルを編集している方かと思われます。
それを踏まえた上で、
以下のような記述をテンプレートファイル内で見かける、あるいは使用したことはないでしょうか?
テンプレートファイルでよく見かけるメインループの記述
if ( have_posts() ):
while ( have_posts() ) : the_post();
// コンテンツの表示処理(the_title()など)
endwhile;
endif;
これが実は、先ほどの「WordPressが記事を出力する流れ」で出てきた⑥に該当する処理になっています。
このようにそのページへアクセスがあったときにWordPressがURLを元に自動的に記事情報を取得する処理のことをメインループと呼びます。
WP_Queryの役割(サブループ)
先ほど
「そのページへアクセスがあったときにWordPressがURLを元に自動的に記事情報を取得する処理のことをメインループと呼ぶ」
とお伝えしました。
では、このメインループで自動取得される記事情報とは別に記事を取得するにはどのような方法があるのでしょうか?
そこで登場するのが、この記事の主役となるWP_Query(サブループを作成するための仕組み)です。
サブループ
WP_Query(サブループを作成するための仕組み)は、簡単に言うとメインループ以外で記事情報を取得するための仕組みです。
これを利用することで、例えば任意のページに「そのページに関連した記事一覧」を表示するといったカスタマイズが可能になります。
メインループ以外で記事情報を取得→出力したいときに利用する仕組みをサブループと呼ぶ
WP_Queryの基本的な使い方
メインループとサブループを簡単に整理すると以下の通りです。
- メインループ
-
- WordPressが、アクセスされたURLを元に自動実行する記事情報の取得処理
- サブループ
-
- メインループとは別に記事情報を取得して出力したい場合に使用する処理
ここからは、具体的なサブループの使用方法(記述方法)を解説していきます。
WP_Query(サブループ)の基本構造
// 1.サブループの条件指定
$args = array(
// ここに呼び出したい記事の条件パラメータを記述
);
// 2.サブループ用のクエリを生成=記事情報を取得
$query = new WP_Query( $args ); // 変数名は任意
// 3.クエリを回して取得した記事を1件ずつ出力する
if ( $query->have_posts() ):
while ( $query->have_posts() ) : $query->the_post();
// コンテンツの表示処理(the_title()など)
endwhile;
endif;
// 4.投稿データのリセット
wp_reset_postdata();
?>
上記のソースコードのように、WP_Queryを利用してサブループを作成する際には
大きく分けて4つのパーツを利用します。
この内、「3.クエリを回して取得した記事を1件ずつ出力する」の処理はメインループの記述にそっくりなのが分かります。
- 取得したい記事条件を指定
- ①を元に記事情報を取得
- ②で取得した記事情報を出力
- 最後にメインループを元に戻す(※別途解説します)
使用例
ここではいくつか使用例を提示します。
(例)カテゴリースラッグが「sample」の投稿を10件取得する
$args = array(
'category_name' => 'sample', // カテゴリースラッグ「sample」を指定
'post_type' => 'post', // 「投稿」を指定
'posts_per_page' => 10, // 表示件数を「10件」に指定
);
$query = new WP_Query( $args );
if ( $query->have_posts() ):
while ( $query->have_posts() ) : $query->the_post();
the_title(); //「投稿タイトル」を出力
the_content(); //「投稿本文」を出力
endwhile;
endif;
wp_reset_postdata();
?>
(例)投稿を「新しい順」に10件取得する
$args = array(
'post_type' => 'post', // 「投稿」を指定
'posts_per_page' => 10, // 表示件数を「10件」に指定
'order' => DESC // 「降順」に並び替え
'orderby' => date // 「日付」順に並び替え
);
$query = new WP_Query( $args );
if ( $query->have_posts() ):
while ( $query->have_posts() ) : $query->the_post();
the_title(); //「投稿タイトル」を出力
the_content(); //「投稿本文」を出力
endwhile;
endif;
wp_reset_postdata();
?>
以上がWP_Queryの使用方法です!
基本的な構造は変わらないため、「条件の指定の仕方」さえ理解してしまえば使い方にはそれほど迷わないかと思います。
wp_reset_postdata()について
最後に「wp_reset_postdata()」の意義について解説します。
記事の最初の方でメインループの流れをご説明したとき
「WordPressが自動取得した記事情報はグローバル変数に格納される」とお伝えしました。
このグローバル変数は「$wp_query」という名前で定義されています。
また、サブループで記事情報を取得した際にも、実はその記事情報というのは「$wp_query」に格納されます。
どういうこと……?
具体的には、サブループでは以下のような流れで処理が実行されます。
- 指定された条件で記事情報を取得
- ①で取得した記事情報は、メインループ情報が格納されている$wp_queryを上書きする形で保存される
※つまり、ここで一時的にメインループの情報が消滅してしまう - if文~while文の処理の部分で、$wp_query内から①で取得した記事情報をひとつずつ取り出す
- wp_reset_postdata()で$wp_queryの中身をメインループの情報に戻す
※これによりサブループで取得した記事情報は消滅する
ポイントとしては以下の通りです。
- メインループで使用されるグローバル変数$wp_queryは、WordPress全体で共有して使用される
- サブループで$wp_queryを上書きしている
- そのため、サブループの最後にメインループ情報を復元しないと、その後のメインループ内の情報がサブループのものに置き換わってしまっているため出力内容に不具合が発生する
そのため、wp_reset_postdata()はサブループを用いる際には必ず記述しなければいけない処理であり、おまじない的な関数という位置づけにあります。
WP_Queryで使用可能なパラメータ一覧
以下は、WP_Queryで使用可能なパラメータの一覧です。
サブループを使用する際にお役立てください。
参考にしたサイト:https://rishuntrading.co.jp/blog/wordpress/wp_query-get_posts-code-snippet/
固定・投稿ページ
$args = array(
'p' => 10, // 投稿IDを指定
'name' => 'post_sample', // 投稿スラッグを指定
'page_id' => 10, // 固定ページのIDを指定
'pagename' => 'page_sample', // 固定ページスラッグを指定
'pagename' => 'parent/child_sample', // 子ページを表示する場合「親のスラッグ/子のスラッグ」の形式で指定
'post_parent' => 10, // 指定したページIDの子ページを検索
'post_parent__in' => array( 10, 11, 12 ), // 親ページIDを含む投稿を検索(配列)
'post_parent__not_in' => array( 10, 11, 12 ), // 親ページIDを含まない投稿を検索(配列)
'post__in' => array( 10, 11, 12 ), // 該当の投稿IDで検索(配列)
'post__not_in' => array( 10, 11, 12 ), // 該当の投稿IDを含まない投稿を検索(配列)
);
カテゴリー
$args = array(
'cat' => 3, // カテゴリIDを指定
'category_name' => 'sample01, sample02', // カテゴリのスラッグで指定(複数は","(カンマ)区切り)
'category__and' => array( 1, 3 ), // カテゴリIDを指定(配列)(該当のカテゴリIDで検索)
'category__in' => array( 1, 3 ), // カテゴリIDを指定(配列)(該当のカテゴリIDで検索)
'category__not_in' => array( 2, 8 ), // カテゴリIDを指定(配列)(該当のカテゴリIDを含まない記事wp検索)
);
タグ
$args = array(
'tag' => 'sample', // タグのスラッグを指定
'tag_id' => 5, // タグIDを指定
'tag__and' => array( 2 , 6 ), // タグIDを指定(配列)(該当のタグIDで検索)
'tag__in' => array( 2 , 6 ), // タグIDを指定(配列)(該当のタグIDで検索)
'tag__not_in' => array( 2 , 6 ), // タグIDを指定(配列)(該当のタグIDを含まない記事を検索)
'tag_slug__and' => array( 'sample01', 'sample02' ), // タグスラッグを指定(配列)(タグスラッグを含む記事を検索)
'tag_slug__in' => array( 'sample01', 'sample02' ), // タグスラッグを指定(配列)(タグスラッグを含む記事を検索)
);
カスタム投稿
$args = array(
// ひとつだけ指定する場合
'post_type' => 'post'; // 投稿
// 複数指定する場合は配列を使用
'post_type' => array(
'post', // 投稿
'page', // 固定ページ
'revision', // リビジョン
'attachment', // 添付ファイル
'custom-post-type' // カスタム投稿タイプのスラッグ
),
// 全てのpost_typeを表示(revisionと'exclude_from_search'がtrueにセットされたものは除く)
'post_type' => 'any',
);
並び順(ソート)
$args = array(
'order' => 'DESC', // 'ASC' 昇順 1, 2, 3 a, b, c
// 'DESC' 降順 3, 2, 1 c, b, a
'orderby' => 'date', // デフォルト値'date'
// 複数指定も可能
'orderby' => 'date title'
);
orderbyで指定可能なパラメータ一覧
パラメータ名 | ソート対象 |
---|---|
none | 並び替えなし |
ID | 投稿ID |
author | 著者 |
name | 投稿スラッグ |
modified | 更新日 |
parent | 親ページID |
rand | ランダム順 |
comment_count | コメント数 |
menu_order | ページの表示順 |
meta_valuee | アルファベット順 |
meta_value_num | 数値 |
post_in | post__inで配列で指定された投稿IDの並び順 |
タクソノミー(カテゴリーやタグも指定可能)
$args = array(
// ひとつのタクソノミーを指定
'tax_query' => array(
array(
'taxonomy' => 'sample', // タクソノミーのスラッグを指定
'field' => 'slug', // term_id, name, slug のいずれかの検索対象のタームのフィールド
'terms' => array( 'saitama', 'tokyo' ), // fieldに指定した検索対象フィールドの検索値(配列)
'include_children' => true, // 子孫タクソノミーを含めるかどうか
'operator' => 'IN' // 'IN','NOT IN','AND','EXISTS','NOT EXISTS'が利用可能
),
)
//複数のタクソノミー条件は'AND'や'OR'で結ぶ
'tax_query' => array(
'relation' => 'AND', // タクソノミーの検索条件に 'AND' か 'OR'指定
array(
'taxonomy' => 'prefecture',
'field' => 'slug',
'terms' => array( 'saitama', 'tokyo' ),
'include_children' => true,
'operator' => 'IN'
),
array(
'taxonomy' => 'contry',
'field' => 'id',
'terms' => array( 122, 132, 141 ),
'include_children' => false,
'operator' => 'NOT IN'
)
)
);
カスタムフィールド
$args = array(
// ひとつのカスタムフィールドを指定する場合
'meta_key' => 'key', // カスタムフィールドのキーを指定
'meta_value' => 'value', // カスタムフィールドの値を指定(文字列)
'meta_value_num' => 10, // カスタムフィールドの値を指定(数字)
'meta_compare' => '=', //「meta_value」に対する演算子('!='、'>'、'>='、'<'、'='の5つが使用可能)
'meta_query' => array( // カスタムフィールドのパラメーター
array(
'key' => 'sample_k', // カスタムフィールドのキー
'value' => 'sample_v', // カスタムフィールドの値 (※compareの値が'IN'、'NOT IN'、'BETWEEN'、'NOT BETWEEN'のみ配列をサポート)
'type' => 'CHAR', // カスタムフィールドの型
'compare' => '=', // 演算子の指定
),
),
// 複数のカスタムフィールド条件は'AND'や'OR'で結ぶ
'meta_query' => array(
'relation' => 'AND', // カスタムフィールドの検索条件に 'AND' か 'OR'指定
array(
'key' => 'sample_k',
'value' => 'sample_v',
'type' => 'CHAR',
'compare' => '=',
),
array(
'key' => 'sample_k02',
'value' => array( sample_v01, sample_v02 ),
'compare' => 'NOT LIKE',
)
),
);
meta_queryのcompareで指定可能なパラメータ一覧
演算子 | 意味 |
---|---|
= | 値が一致 |
!= | 値が一致しない |
> | 「演算子の左」が「演算子の右」より大きい |
>= | 「演算子の左」が「演算子の右」以上 |
< | 「演算子の左」が「演算子の右」より小さい |
<= | 「演算子の左」が「演算子の右」以下 |
LIKE | 「演算子の左」が「演算子の右」に一致 |
NOT LIKE | 「演算子の左」が「演算子の右」に一致しない |
IN | 値(配列)で指定したいずれかに一致 |
NOT IN | 値(配列)で指定したいずれにも一致しない |
BETWEEN | 2つの値で指定した範囲内(境界を含む)である |
NOT BETWEEN | 2つの値で指定した範囲外である |
投稿の状態(公開・下書きなど)
$args = array(
// ひとつだけ指定する場合
'post_status' => 'publish', // 公開状態
// 複数指定する場合は配列を使用
'post_status' => array( // 投稿の状態を指定
'publish', // 公開状態
'pending', // レビュー待ち状態
'draft', // 下書き状態
'auto-draft' // コンテンツのない、新しく作成された投稿/ページを表示
'future', // 予約公開が設定された状態
'private', // ログインしたユーザーしか見れない状態
'inherit', // リビジョン
'trash', // ゴミ箱に入っている状態
),
// すべての状態(post_statusで'exclude_from_search'がtrueにセットされたものは除く)
'post_status' => 'any',
);
著者
$args = array(
'author' => '1,2,3', // 著者のユーザIDを指定
'author_name' => 'kekenta', // user_nicenameを指定(ログイン名(user_login)ではないです)
'author__in' => array( 2 , 6 ), // 該当のユーザーIDが含む記事で指定
'author__not_in' => array( 2 , 6 ), // 該当のユーザーIDを含まない記事で指定
);
日付・時間
$args = array(
'date_query' => array(
array(
'year' => 2021, // 年を指定(2021など)
'month' => 8, // 月を指定(1~12)
'week' => 31, // 年内の週を指定(0~53)
'day' => 5, // 月内の日を指定(1~31)
'hour' => 2, // 時間を指定(0~23)
'minute' => 3, // 分を指定(0~60)
'second' => 36, // 秒を指定(0~60)
'after' => array( // 指定した日付以降の投稿を取得 → 「'after'=>'2020/02/28'」という指定も可能
'year' => 2013, // 年を指定(2013など) デフォルトは空
'month' => 2, // 年内の月を指定(1~12) デフォルトは12
'day' => 28, // 月内の日を指定(1~31) デフォルトは月内の末日
)
'before' => array( // 指定した日付以前の投稿を取得 → 「'before'=>'2020/02/28'」という指定も可能
'year' => 2013,
'month' => 2,
'day' => 28,
),
'inclusive' => true, // 「after」or「before」で指定された値を含むかどうか
'compare' => '=', // '=', '!=', '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN', 'EXISTS' , and 'NOT EXISTS'が使用可能
'column' => 'post_date', // 照会するカラムを指定
),
),
// 「期間」を指定する場合は'AND'や'OR'で結ぶ
'date_query' => array(
'relation' => 'AND',
array(
'year' => 2013,
'month' => 2,
'compare' => '>='
),
array(
'year' => 2013,
'month' => 8,
'compare' => '<='
),
),
);
ページ送り
$args = array(
'posts_per_page' => 10, // 1ページに表示できる最大投稿数(「-1」は全て表示)
'posts_per_archive_page' => 10, // 1ページに表示できる最大投稿数(アーカイブページのみ)
'nopaging' => false, // ページ送りの有効/無効
'paged' => 3, // ページ番号3の記事一覧を表示
'paged' => get_query_var('paged'), // 現在のページから投稿を表示
'offset' => 10, // 設定した数だけ、ずらして表示(例では11番目の投稿から表示)
'ignore_sticky_posts' => false, // 先頭の固定表示投稿を無視するかどうか(false=先頭の固定表示投稿は無視しない)
);
パスワード
$args = array(
'has_password' => true, // パスワード付きの投稿を検索( true or false )
'post_password' => 'birthday1111', // 該当のパスワードが付いた投稿を検索
);
WP_Queryを活用すれば記事情報を自由に扱える
いかがだったでしょうか。
WordPressには「メインループ」と「サブループ」という大きく2種類の記事取得の仕組みが備わっています。
今回ご紹介したのはこの内の「サブループ」を扱うための仕組みWP_Queryの使用方法でした。
WP_QueryはWordPressでサイト制作を行うなら使用必須の仕組みです。
また、これを上手く扱えるようになれば、任意のページで好きな記事情報を自由に引き出すことが可能です。
WordPressは簡単にサイト制作が行えるCMSである一方、本当の意味で使いこなそうとすると実は覚えることや理解すべきことがたくさんあります。
この記事がその一助となったなら何よりです。
それでは、最後までご覧いただきありがとうございました。
当ブログではWordPressやWeb制作、PHPに関する記事を発信しています。
ご興味のある方はほかの記事もご覧いただけると嬉しいです。
コメント