べんりワザ・WordPressのテンプレートと投稿の取得

関連記事をプラグインなしで出す

同じカテゴリ・タグ・タクソノミーから関連記事を出すコード集。自分自身の除外、0件のときの代わりの一覧、手動で選ばせる方法まで、プラグインを入れずに作るパターンをまとめました。

関連記事はプラグインなしで作れます。同じカテゴリ(またはタグ・タクソノミー)の投稿をWP_Queryで取り、自分自身を除くだけ——20行ほどで、見た目も自由に作れます。

<?php
$related = new WP_Query([
  'category__in'        => wp_get_post_categories(get_the_ID()),
  'post__not_in'        => [get_the_ID()],
  'posts_per_page'      => 4,
  'ignore_sticky_posts' => true,
  'orderby'             => 'rand',
]);
?>
<?php if ($related->have_posts()) : ?>
  <section class="related">
    <h2>関連記事</h2>
    <ul class="cards">
      <?php while ($related->have_posts()) : $related->the_post(); ?>
        <li>
          <a href="<?php the_permalink(); ?>">
            <?php if (has_post_thumbnail()) : ?>
              <?php the_post_thumbnail('medium'); ?>
            <?php endif; ?>
            <h3><?php the_title(); ?></h3>
          </a>
        </li>
      <?php endwhile; ?>
    </ul>
  </section>
<?php endif; ?>
<?php wp_reset_postdata(); ?>

押さえるのは3つ——post__not_inで自分を除く、ifで0件のときに見出しを出さない、最後にwp_reset_postdata()

べんりワザループの外で投稿を取得する方法(WP_Query)サブループの基本と後始末の理由はこちら

パターン1:同じタグから(精度が高い)

カテゴリは大きなくくりなので、タグのほうが「近い記事」を拾えます

<?php
$tags = wp_get_post_tags(get_the_ID(), ['fields' => 'ids']);
$related = new WP_Query([
  'tag__in'        => $tags,
  'post__not_in'   => [get_the_ID()],
  'posts_per_page' => 4,
]);
?>

タグが付いていない記事では0件になるので、次のフォールバックとセットで使うのが実用的です。

パターン2:タグ優先、足りなければカテゴリで補う

「精度の高い順に埋めていく」いちばん実用的な形です。

<?php
$post_id = get_the_ID();
$exclude = [$post_id];
$items   = [];

// ① まずタグが同じ記事
$by_tag = get_posts([
  'tag__in'      => wp_get_post_tags($post_id, ['fields' => 'ids']),
  'post__not_in' => $exclude,
  'numberposts'  => 4,
]);
$items = $by_tag;

// ② 足りなければカテゴリが同じ記事で補う
if (count($items) < 4) {
  $exclude = array_merge($exclude, wp_list_pluck($items, 'ID'));
  $by_cat  = get_posts([
    'category__in' => wp_get_post_categories($post_id),
    'post__not_in' => $exclude,
    'numberposts'  => 4 - count($items),
  ]);
  $items = array_merge($items, $by_cat);
}
?>
<?php if ($items) : ?>
  <ul class="cards">
    <?php foreach ($items as $item) : ?>
      <li>
        <a href="<?php echo esc_url(get_permalink($item)); ?>">
          <?php echo get_the_post_thumbnail($item, 'medium'); ?>
          <h3><?php echo esc_html(get_the_title($item)); ?></h3>
        </a>
      </li>
    <?php endforeach; ?>
  </ul>
<?php endif; ?>

wp_list_pluck($items, 'ID')は「配列からIDだけ抜き出す」WordPressの便利関数です。これをpost__not_inに渡して同じ記事が2回出るのを防ぎます

パターン3:カスタムタクソノミーから

カスタム投稿タイプのサイトでは、独自のタクソノミーが関連付けの軸になります。

<?php
$terms = wp_get_post_terms(get_the_ID(), 'season', ['fields' => 'ids']);
$related = new WP_Query([
  'post_type'      => 'shohin',
  'post__not_in'   => [get_the_ID()],
  'posts_per_page' => 4,
  'tax_query'      => [
    ['taxonomy' => 'season', 'field' => 'term_id', 'terms' => $terms],
  ],
]);
?>
べんりワザtax_queryでカテゴリ・タクソノミーで絞りこむtax_queryの書き方(複数条件・AND/OR)はこちら

パターン4:手動で選ばせる(ACFの関連フィールド)

自動の関連付けは、記事数が少ないうちは的外れになりがちです。編集画面で選ばせるのが確実な方法です。ACF(SCF)の「関連(relationship)」フィールドを使います。

<?php $picks = get_field('related_items'); ?>
<?php if ($picks) : ?>
  <ul class="cards">
    <?php foreach ($picks as $item) : ?>
      <li>
        <a href="<?php echo esc_url(get_permalink($item)); ?>"><?php echo esc_html(get_the_title($item)); ?></a>
      </li>
    <?php endforeach; ?>
  </ul>
<?php endif; ?>

手動で選ばれていればそれを出し、無ければ自動——という合わせ技が実務では強いです。

<?php if ($picks = get_field('related_items')) : ?>
  <!-- 手動で選ばれたものを出す -->
<?php else : ?>
  <!-- 自動の関連記事を出す -->
<?php endif; ?>
べんりワザACFフィールド別・表示の書き方早見表ACFの関連フィールドなど、種類別の書き方はこちら

0件のときは「最新記事」で埋める

関連記事の見出しだけ残るのは、いちばん避けたい見た目です。

<?php if ($related->have_posts()) : ?>
  <h2>関連記事</h2>
  <!-- 関連の一覧 -->
<?php else : ?>
  <h2>最近の記事</h2>
  <?php $recent = new WP_Query(['posts_per_page' => 4, 'post__not_in' => [get_the_ID()]]); ?>
  <!-- 最新の一覧 -->
  <?php wp_reset_postdata(); ?>
<?php endif; ?>

プラグインを使わない利点

  • 軽い——関連記事プラグインは、候補を探すために重い処理をすることがある
  • 見た目が自由——カードの形もクラス名も自分のCSSに合わせられる
  • 条件を決められる——「同じ季節の商品だけ」「自分を除く」など要件どおりに書ける

一方で、記事数が数千件を超えるサイトで複雑な関連度計算をしたい場合は、専用プラグインや検索エンジン連携のほうが向いています。まずは自作、行き詰まったら道具を足す——この順番がおすすめです。

まとめ

  1. 関連記事はWP_Query同じカテゴリ・タグ・タクソノミーを取るだけ。プラグインは不要
  2. 'post__not_in' => [get_the_ID()]で自分自身を除く
  3. タグ優先→カテゴリで補う形にすると精度と件数のバランスが取れる
  4. 手動で選ばせるなら関連フィールド、0件のときは最新記事で埋める

「次に読むもの」を自分で設計できると、サイトの回遊がぐっと良くなります。

よくある質問

関連記事はプラグインなしで作れますか?
作れます。WP_Queryで同じカテゴリやタグの投稿を取得し、post__not_inで自分自身を除くだけです。20行ほどのコードで、プラグインより軽く自由な見た目にできます。
関連記事に今読んでいる記事が混ざります
'post__not_in' => [get_the_ID()] を条件に足してください。これが無いと自分自身も候補に入ります。
関連記事が0件のときはどうすればいいですか?
elseで最新記事や人気記事の一覧を出すのが定番です。空の見出しだけが残る状態は避けたいので、代わりの一覧を用意しておきます。
タグが同じ記事を優先したいです
まずタグ条件で取得し、件数が足りなければカテゴリ条件で追い足す方法があります。取得済みのIDをpost__not_inに渡して重複を防ぎます。