TOPページに複数の投稿一覧を表示する、とあるカテゴリーのページに別のカテゴリー一覧の記事を表示させたい(メインクエリとは異なる投稿を表示させたい)場合は「サブループ」というものを使います。これはWordPressでサイトを作る時には押さえておきたい仕組みです。
サブループを作るときは、WP_Query
クラスと get_posts
関数を使う2つの方法があります。これらの違いとそれぞれのループの作り方をご紹介します。
WordPressのループ
ループとは投稿を表示するための仕組みのことを指します。ページによってどの投稿を表示させるか、というのはデフォルトで決められています。
デフォルトの状態のループをメインループ、それ以外にカスタマイズして任意の投稿を取得したいときに使われるのがサブループです。
ここではメインループでは取得できない投稿を表示させたいときに使用するサブループの使い方をご紹介していきます。
WP_Query と get_postsの違いと使い分け
WP_Query
はクラス、 get_posts
はラッパー関数と呼ばれるもので、書き方やパラメータが一部異なります。また「取得できる情報量」も違います。
get_posts
は内部で WP_Query
を使用し、いろいろな条件を絞り込んで処理を簡単にしているものです。そのため WP_Query
の方がいろいろな条件を指定できます。
複雑な条件を指定して情報を取得したい、後から仕様変更の可能性があって幅広く対応させられるようにしておきたい場合は WP_Query
を使用した方が、書き直しの手間が省きやすく修正しやすいので無難かなと思います。単純にタイトル・コンテンツ・日付などよく使うものなら get_posts
で十分対応できます。
自分にとって使いやすい方やループ内での表示のさせ方を考えながら使い分けていきましょう。
返り値・書き方の違い
- 【WP_Query】→「オブジェクト」(記事情報 + ページ情報)
- 【get_posts】→「配列」(記事情報のみ)
WP_Query
は記事情報以外にページ情報があるので is_single()
といった条件分岐が使えますが、get_posts
では使えません。
ループの回し方も変わります。
- 【WP_Query】→「while文でループ」
- 【get_posts】→「foreach文でループ」
get_posts
は、have_posts()
や the_post()
といった記述を省けます。(少しコードがスッキリする)
最新の記事を何件か取得してタイトルと記事の一部内容だけ表示する、という場合には get_posts()
で十分です。
「ループの途中で何か処理を追加したい」といったことや「記事データ以外に表示されているページそのものの情報も取得したい」場合などは WP_Query
を使って対応します。
パラメーターの違い
使えるパラメーターはほとんど同じですが、get_posts
特有パラメーター指定もあります。
取得情報 | get_posts で使えるパラメーター | WP_Query のパラメーター |
---|---|---|
取得する投稿数 | numberposts | posts_per_page |
カテゴリー指定 | category | cat |
取得する投稿 | include | post__in |
除外する投稿 | exclude | post__not_in |
表の「WP_Query のパラメーター」の列に書かれているパラメーターは、 get_posts
でも WP_Query
でも利用できます。
「get_posts で使えるパラメーター」は WP_Query
の引数に指定しても無視されてしまうので、うまく取得できない場合はパラメーターを見直してみてください。
numberpostsとposts_per_page
numberposts
は posts_per_page
のエイリアス(別名)ですが、初期に取得する投稿数が異なります。posts_per_page
の初期値はページ毎に指定されている数で、numperposts
の初期値は「5」です。
get_posts
にはこの numberposts
の投稿数が初期値として入っており、numberposts
または posts_per_page
で表示件数を指定しない場合は、5件の投稿が表示されます。
categoryとcat
category
と cat
は表記の違いのみです。
includeとpost__in、excludeとpost__not_in
特定の投稿IDを取得・除外したいときに使えるのがこれらのパラメーターです。
include と exclude は配列指定、もしくはカンマ区切の文字列でも指定できますが、post__in と post__not_in は配列での指定のみ有効です。
$args = array (
// どちらでもOK
'include' => '10, 12, 14',
'include' => array(10, 12, 14),
);
$args = array (
// どちらでもOK
'exclude' => '9, 13, 16',
'exclude' => array(9, 13, 16),
);
$args = array (
'post__in' => array(10, 12, 14),
);
$args = array (
'post__not_in' => array(9, 13, 16),
);
WP_Query() を使った基本コード
WP_Query
は、データベースから投稿データを取得するクラスです。get_posts
より様々な条件指定ができます。
<?php
// 取得したい投稿内容の条件を指定
$args = array(
'post_type' => 'my_posts',
'posts_per_page' => 3,
'cat' => '10',
'no_found_rows' => true;
);
// オブジェクト取得
$my_posts = new WP_Query($args);
// ループの開始
while ($my_posts->have_posts()):
$my_posts->the_post();
?>
<!-- 表示させたい投稿内容 -->
<h1><?php the_title(); ?></h1>
<div><?php the_content(); ?></div>
<!-- 投稿表示終了。メインクエリの値に戻す -->
<?php endwhile; wp_reset_postdata();?>
上記の11行目にあるコードで新しいクエリを設定して記事を取得しています。
$my_posts = new WP_Query($args);
引数にある $args
は配列形式で設定するパラメータを指定します。
「どういった内容の記事を取得するか」ということをここで決めているわけです。
$args = array(
'post_type' => 'my_posts',
'posts_per_page' => 3,
'cat' => '10',
'no_found_rows' => true,
);
上記のコードでは以下に当てはまる記事を取得します。
- 投稿タイプは「my_posts」
- 表示する件数は「3件」
- カテゴリーIDが「10」のもの
- ページングを無効化
「ページングの無効化」についてはこの記事を参考に取り入れました。
WP_Query関数のno_found_rowsパラメータについて
指定のないパラメータは初期値が使われます。指定できるパラメータはたくさんあるので、取得したい条件があるときは参考にしましょう。
よく使うものはこの記事内でもまとめています。
#args(引数)によく使うものとその内容
投稿の表示条件を指定して新しいクエリを取得したら、ループを使用して出力します。このループがサブループです。
<?php
while ($my_posts->have_posts()):
$my_posts->the_post();
?>
<!-- 表示させたい投稿内容 -->
<h1><?php the_title(); ?></h1>
<div><?php the_content(); ?></div>
<!-- 投稿表示終了。メインクエリの値に戻す -->
<?php endwhile; wp_reset_postdata();?>
$my_posts->
という記述が追加される以外はメインループと同じ記述でOKです
WP_Query
を使ったサブループの場合は wp_reset_postdata()
をつけることをお忘れなく。メインクエリを変更しているため、サブループ後にメインクエリの内容を表示させる、他のサブループを使うといった場合にはリセットする必要があります。
そうしないと意図した投稿が表示されません。
サブループの後にメインクエリのデータを使わないのであれば、必ず必要なものではありません。ですが、思わぬところでメインクエリのデータが必要だったりもします。
条件分岐のコードがうまく動作しなかったりするので、セットで付けるくせをつけていた方がエラーの発生を抑えられます。
get_posts() を使った基本コード
get_posts()
の返り値は「クエリにマッチした投稿の配列」です。
関数内部では WP_Query()
が使われていて、よりシンプルな値を返します。
WP_Query()
はwhile文でしたが、get_posts()
はforeach文を使います。
<?php
// 取得したい投稿内容
$args = array(
'post_type' => 'my_posts',
'posts_per_page' => 3,
'category' => '10',
'no_found_rows' => true,
);
// クエリオブジェクト取得
$my_posts = get_posts($args);
// ループの開始
foreach ($my_posts as $val):
$title = $val->post_title;
$content = $val->post_content;
?>
<h1><?php echo $title; ?></h1>
<div><?php echo $content; ?></div>
<?php endforeach; ?>
get_posts()
を使った場合、上記の記述では the_title()
といった出力関数が使用できませんが、setup_postdata()
を追加することで使えるようになります。
setup_postdata() で出力関数を使えるようにする
setup_postdata()
はデータをセットします。
グローバルの $post
を書き換えて the_title()
などWP_Query
のメソッドが使えるようになります。
逆にこの記述がないと the_title()
といった出力関数が使えないので、覚えておくと便利です。
<?php
foreach ($my_posts as $val):
global $post;
$post = $val;
// ↑ $valが$postに入る
setup_postdata($post);
// ↑ $valのデータをセットする
?>
<h1><?php the_title(); ?></h1>
<div><?php the_content(); ?></div>
<?php endforeach; wp_reset_postdata();?>
setup_postdata()
を使った時は、WP_Query
を使用した時と同様に wp_reset_postdata()
でループをリセットする必要があります。
一旦ループを終了して再度同じサブループを回す
wp_reset_postdata()
は投稿をリセットしてメインクエリの状態に戻しますが、サブループを一旦終了して再度サブループを回したい時に、この関数を使うともう一度同じコードを書かなくてはならないので手間です。
同じサブループでもう一度まわしたい時はこのように書きます。
endwhile;
$the_query->reset_postdata();
//この後にもう一度 $the_query->have_post() で始められる
覚えておきたいパラメーター
基本的なサブループの作り方がわかれば、あとは「どういった投稿を表示させるか」という指定の部分をカスタマイズしていくのが主となります。どのような設定があるのかを知っていると多彩な表示方法ができるようになります。
そこで覚えておきたいのがパラメーターです。指定できるものがたくさんあって、全てを使いこなすのはなかなか大変ですが、いくつかよく使うものをまとめていきます。
$args = array(
'post_type' => 'my_posts',
'posts_per_page' => 3,
'cat' => '10',
'tag' => 'tagslug',
'category_name' => 'cat1',
'order' => 'ASC',
'orderby' => 'modified',
'post__not_in' => array(get_the_ID()),
);
投稿タイプの指定 : ‘post_type’
投稿タイプを指定します。デフォルトの値は ‘post’ なので、固定ページやカスタム投稿タイプの一覧を取得したいときに使用します。
通常の投稿 | ‘post’ |
固定ページ | ‘page’ |
カスタム投稿タイプ | ‘作成した投稿タイプ名’ |
以下のように配列にして複数の投稿タイプを指定することもできます。
'post_type' => array('type01','type02'),
1ページに表示させる投稿数 : ‘posts_per_page’
1ページあたりに表示させたい最大投稿数を指定します。全件表示させたい場合は、’-1′ にします。
カテゴリーから記事を指定する : ‘cat’, ‘category’, ‘category_name’
カテゴリーを指定したい場合に使用するのがこれらのパラメーターです。使用するループのコードや値の指定方法が異なるので覚えておきましょう。
私は WP_Query
でも get_posts
でも使え、指定しやすい(IDは覚えられないけどスラッグ名は覚えていることが多いので) category_name
をよく使用します。
cat | WP_Query でも get_posts でも使用できる。「カテゴリーID」を指定する。 |
category | get_posts でのみ使用できる。こちらも「カテゴリーID」を指定WP_Queryで使用しても設定したカテゴリーは表示されない。 |
category_name | WP_Query でも get_posts でも使用できる。「カテゴリースラッグ」を指定する。 |
タグから記事を指定する : ‘tag’
タグを指定する場合はスラッグで指定します。
'tag' => 'tagslug',
IDで指定する場合は 'tag_id'
というパラメーターを使用します。
'tag_id' => 10,
‘order’, ‘orderby’ : 投稿の並び順を指定する
記事一覧の表示順序を指定するために使用するのがこの2つです。
order | 降順(DESC)、昇順(ASC)のどちらかを指定。(初期値は 'DESC' )orderbyで設定した内容の昇順・降順が表示される。 |
orderby | 「どの順序で並び替えるか」を指定。2つ以上でも設定可。'date' …投稿日の日付順(初期値)'modified' …編集日の日付順'rand' …ランダムな並び順 |
orderby にはもっとたくさんの種類があるので、必要な並び順が上記にない場合は以下も参考にしてみて下さい。
‘post_status’ : 投稿の表示状態を指定する
「公開」や「非公開」といった投稿の表示状態を指定して表示させるのが 'post_status'
です。
初期値は「公開」ですが、WordPressにログインしているときは「非公開」の記事も含まれます。WordPressにあまり詳しくないクライアントさんから非公開記事も一覧に出てきているのですが。。。なんて言われてしまった時は 'post_status' => 'publish',
を追加して、どの状態でも公開記事のみ表示されるようにしましょう。
‘post__not_in’ : 特定の記事を除外
'post__not_in'
は除外したい投稿を指定するパラメーターです。
例えばシングルページに関連記事を表示させる場合、現在の投稿ページのリンクは表示させても意味がありません。こういった時に使えるのが、'post__not_in'
です。
'post__not_in'
の値は配列で指定します。
$args = array(
'post_type' => 'my_posts',
'posts_per_page' => 3,
'orderby' => 'rand',
'post__not_in' => array(get_the_ID()),
);
グローバル変数 $post
を使用して以下のように書くこともできます。
global $post;
$args = array(
'post_type' => 'my_posts',
'posts_per_page' => 3,
'orderby' => 'rand',
'post__not_in' => array($post->ID),
);
ループが表示されない時に見直したいところ
正しいパラメーターを使用しているか、値が間違っていないか(idやスラッグは正しいか)を確認してみて下さい。パラメーターの区切りがちゃんとできていなかったり、カンマ「,」が抜けてしまっていたり、結構些細なミスで表示されないことも多いので、コードの書き方に間違いがないかも見直してみましょう。
ループに query_posts() は使わない
query_posts()
というメインクエリを変更する関数があって、一昔前はこれを使っていました。このコードは「WordPressのコアコードの中だけで使われるもの」とされていて、テーマ内で使用するのは非推奨とされています。
予期しない動作やエラーが発生する可能性が高くなるため、もし記述があったらできる限り変更しましょう。