WP_Query や get_posts を使ったサブループの投稿一覧表示方法

TOPページに複数の投稿一覧を表示する、とあるカテゴリーのページに別のカテゴリー一覧の記事を表示させたいといったように、メインループでは取得できない投稿を表示させたい場合は、サブループというものを使います。

サブループを作るときは、WP_Query クラスと get_posts 関数を使う2つの方法があります。それぞれのループの作り方と違いをご紹介します。

基本コード

まずは基本のコードの書き方から。タイトルと本文を表示させるループの例です。

処理の流れは、取得・表示させたい投稿を指定 → WP_Query または get_posts を使って条件に当てはまった投稿データを変数に格納 → 繰り返し処理を行うです。

WP_Queryの基本コード

WP_Query は、データベースから投稿データを取得するクラスです。get_posts より様々な条件指定ができます。

while文でループを回します。

PHP
<?php
  // 取得したい投稿内容の条件を指定
  $args = array(
    // 取得したい投稿の条件
  );
  $the_query = new WP_Query($args);

  // ループの開始
  while ($the_query->have_posts()):
    $the_query->the_post();
?>
  <!-- 表示させたい投稿内容 -->
  <h1><?php the_title(); ?></h1>
  <div><?php the_content(); ?></div>

<!-- 投稿表示終了。メインクエリの値に戻す -->
<?php endwhile; wp_reset_postdata();?>

投稿の表示条件を指定して新しいクエリを取得したら、ループを使用して出力します。このループがサブループです。

PHP
<?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
<?php
  $args = array(
    // 取得したい投稿の条件
  );
  $the_posts = get_posts($args);

  // ループの開始
  foreach ($the_posts as $val):
    $title = $val->post_title;
    $content = $val->post_content;
?>
  <h1><?php echo $title; ?></h1>
  <div><?php echo $content; ?></div>

<?php endforeach; ?>

取得する投稿の条件をパラメーターを使って指定

引数にある $args は配列形式で設定するパラメータを指定します。
「どういった内容の記事を取得するか」ということをここで決めているわけです。

例えば以下に当てはまる記事を取得します。

  • 投稿タイプは「my_posts」
  • 表示する件数は「3件」
  • カテゴリーIDが「10」のもの
  • ページングを無効化

「ページングの無効化」についてはこの記事を参考に取り入れました。
WP_Query関数のno_found_rowsパラメータについて

この条件に当てはめるコードはこちら。

PHP
  $args = array(
    'post_type' => 'my_posts',
    'posts_per_page' => 3,
    'cat' => '10',
    'no_found_rows' => true,
  );

基本的なサブループの作り方がわかれば、あとは「どういった投稿を表示させるか」という指定の部分をカスタマイズしていくのが主となります。指定のないパラメータは初期値が使われます。

どのようなパラメーターがあるかを知っていると、多彩な表示方法ができるようになります。指定できるものがたくさんあるため、以下の記事にまとめました。

以下のコードで取得したデータを変数に格納しています。

PHP
$the_query = new WP_Query($args);

$the_posts = get_posts($args);

WP_Query と get_postsの違いと使い分け

WP_Query はクラス、 get_posts はラッパー関数と呼ばれるもので、書き方やパラメータが一部異なります。また取得できる情報量も違います。

自分にとって使いやすい方でも良いですが、表示内容によって使い分けていきましょう。

get_posts は、条件を絞り込んで WP_Query を使用した結果のみが返され、処理を簡単にしています。
投稿の取得条件とその結果を保持する WP_Query の方がループ内でできることが多いです。

単純にタイトル・コンテンツ・日付といった投稿の基本情報のみ出力させるだけでよければ get_posts で十分対応できます。

「ループの途中で何か処理を追加したい」といったことや「記事データ以外に表示されているページそのものの情報も取得したい」場合などは WP_Query を使って対応します。後から仕様変更の可能性があって幅広く対応させられるようにしておきたい場合も WP_Query を使用した方が、書き直しの手間が省きやすく修正しやすいので無難かなと思います。

返り値・書き方の違い

  • 【WP_Query】→「オブジェクト」(記事情報 + ページ情報)
  • 【get_posts】→「配列」(記事情報のみ)

WP_Query は記事情報以外にページ情報があるので is_single() といった条件分岐が使えますが、get_posts では使えません。

ループの回し方も変わります。

  • 【WP_Query】→「while文でループ」
  • 【get_posts】→「foreach文でループ」

get_posts は、have_posts()the_post() といった記述を省けます。(少しコードがスッキリする)

パラメーターの違い

使えるパラメーターはほとんど同じですが、get_posts 特有パラメーター指定もあります。

取得情報get_posts で使えるパラメーターWP_Query のパラメーター
取得する投稿数numberpostsposts_per_page
カテゴリー指定category cat
取得する投稿includepost__in
除外する投稿exclude post__not_in

表の「WP_Query のパラメーター」の列に書かれているパラメーターは、 get_posts でも WP_Query でも利用できます。
「get_posts で使えるパラメーター」は WP_Query の引数に指定しても無視されてしまうので、うまく取得できない場合はパラメーターを見直してみてください。

また get_posts を使用する場合、$ignore_sticky_posts$no_found_rows は指定しても無視され、「true」に設定されます。

numberpostsとposts_per_page

numberpostsposts_per_page のエイリアス(別名)ですが、初期に取得する投稿数が異なります。
posts_per_page の初期値はページ毎に指定されている数で、numperposts の初期値は「5」です。

get_posts にはこの numberposts の投稿数が初期値として入っており、numberposts または posts_per_page で表示件数を指定しない場合は、5件の投稿が表示されます。

categoryとcat

categorycat は表記の違いのみです。

includeとpost__in、excludeとpost__not_in

特定の投稿IDを取得・除外したいときに使えるのがこれらのパラメーターです。

include と exclude は配列指定、もしくはカンマ区切の文字列でも指定できますが、post__in と post__not_in は配列での指定のみ有効です。

PHP
$args = array (
  // どちらでもOK
  'include' => '10, 12, 14',
  'include' => array(10, 12, 14),
);
PHP
$args = array (
  // どちらでもOK
  'exclude' => '9, 13, 16',
  'exclude' => array(9, 13, 16),
);
PHP
$args = array (
  'post__in' => array(10, 12, 14),
);
PHP
$args = array (
  'post__not_in' => array(9, 13, 16),
);

setup_postdata() で出力関数を使えるようにする

get_posts() を使った場合、先述のコードでは the_title() といった出力関数が使用できませんが、setup_postdata() を追加することで使えるようになります。

setup_postdata() はグローバルの $post を書き換えて the_title() など WP_Query のメソッドが使えるようになるコードです。

逆にこの記述がないと the_title() といった出力関数が使えないので、覚えておくと便利です。

PHP
<?php
  foreach ($the_posts as $post):
    global $post;
    setup_postdata($post);
?>
  <h1><?php the_title(); ?></h1>
  <div><?php the_content(); ?></div>

<?php endforeach; wp_reset_postdata();?>

setup_postdata()$post を書き換えるため、WP_Query を使用した時と同様に wp_reset_postdata() でループをリセットする必要があります。

ループが表示されない時に見直したいところ

正しいパラメーターを使用しているか、値が間違っていないか(idやスラッグは正しいか)を確認してみて下さい。パラメーターの区切りがちゃんとできていなかったり、カンマ「,」が抜けてしまっていたりなど、些細なミスで表示されないことも多いので、コードの書き方に間違いがないかも見直してみましょう。

ループに query_posts() は使わない

query_posts() というメインクエリを変更する関数があって、一昔前はこれを使っていました。このコードは「WordPressのコアコードの中だけで使われるもの」とされていて、テーマ内で使用するのは非推奨とされています。

予期しない動作やエラーが発生する可能性が高くなるため、もし記述があったらできる限り変更しましょう。

カテゴリー : WordPress

index