single.php(個別記事ページ)では、今見ている記事と関連する記事(関連記事) を表示することがよくあります。
特によく使われるのが、
- 同じカテゴリに属する記事
- 表示件数は 3件程度
というパターンです。
目次
なぜ「サブループ」が必要なのか
single.php には、もともと メインループ が存在します。
<?php
if ( have_posts() ) :
while ( have_posts() ) :
the_post();
// 記事本文など
endwhile;
endif;
?>このメインループは、
- 今表示している 1記事専用
- 表示件数や条件を変えられない
という特徴があります。
👉
「関連記事」「別条件の記事一覧」を表示したい場合は、新しくクエリを作る=サブループが必要 になります。
今回やりたいこと(要件整理)
- 表示場所:single.php
- 条件:
- 現在の記事と 同じカテゴリ
- カテゴリは複数選択されている可能性あり
- 件数:3件
- 現在の記事は除外
- 新しいサブループで取得
手順①:現在の記事のカテゴリIDを取得する
$categories = get_the_category();これで、記事に設定されているカテゴリが配列として取得されます。
カテゴリIDだけを配列にする
$category_ids = array();
if ( $categories ) {
foreach ( $categories as $category ) {
$category_ids[] = $category->term_id;
}
}複数カテゴリ対応のための重要ポイントです。
手順②:サブループ用のクエリを作成する
$args = array(
'post_type' => 'post',
'posts_per_page' => 3,
'category__in' => $category_ids,
'post__not_in' => array( get_the_ID() ),
);各引数の意味(初心者向け)
posts_per_page→ 表示件数(今回は3件)category__in→ 指定したカテゴリIDの いずれかに属する記事post__not_in→ 今表示している記事を除外
手順③:サブループを実行する
$related_query = new WP_Query( $args );実際に表示するコード(コピペOK)
<?php
$categories = get_the_category();
$category_ids = array();
if ( $categories ) {
foreach ( $categories as $category ) {
$category_ids[] = $category->term_id;
}
}
$args = array(
'post_type' => 'post',
'posts_per_page' => 3,
'category__in' => $category_ids,
'post__not_in' => array( get_the_ID() ),
);
$related_query = new WP_Query( $args );
if ( $related_query->have_posts() ) :
?>
<div class="related-posts">
<h2>関連記事</h2>
<ul>
<?php while ( $related_query->have_posts() ) : $related_query->the_post(); ?>
<li>
<a href="<?php the_permalink(); ?>">
<?php the_title(); ?>
</a>
</li>
<?php endwhile; ?>
</ul>
</div>
<?php
endif;
wp_reset_postdata();
?>絶対に忘れてはいけないポイント
wp_reset_postdata() を必ず書く
wp_reset_postdata();これを忘れると、
- 以降のテンプレートタグが
- メインループではなくサブループを参照してしまう
👉single.php では特に重要です!
この実装でできること・できないこと
できること
- 複数カテゴリに対応
- 件数指定
- 現在の記事を除外
- デザイン自由
注意点
- カテゴリが設定されていない記事では表示されない
- 「未分類」もカテゴリとして扱われる
初心者向けまとめ
- 関連記事表示には サブループが必要
- 複数カテゴリ対応には
category__in - 今の記事は
post__not_inで除外 - 最後に
wp_reset_postdata()を忘れない
single.php の構造は基本こうですよね👇
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<!-- 記事本文 -->
<!-- ここに関連記事サブループ -->
<?php endwhile; endif; ?>この中では、
- メインループ → 現在の記事
- サブループ → 関連記事
と役割が明確に分かれているため、サブループがメインの $post を一時的に上書きしても、リセットすれば問題なしです。

コメント