WordPressの関連記事を過去の記事だけに限定して表示する方法

WordPressで関連記事を表示させたいことってありますよね。ただ思ったように表示されないこともしばしば。今回も「特定の記事に関連する過去の記事一覧がほしい」というオーダーをいただいたのですが、ちょうど良さそうなプラグインがなかったので作ることになりました。その際の、ソースコードと実装の流れをご紹介していきたいと思います。

プログラムの流れ

プログラムの流れは以下の通りです。WP_Query()で記事一覧を取得して、ショートコードで出力するだけのシンプルな内容です。

  1. functions.phpに関数「out_past_post()」を追加
    ・パラメータを生成(投稿日、カテゴリー一覧)
    ・記事一覧を取得(WP_Query)
    ・出力
  2. ウィジェット等にショートコードを追加

functions.phpに関数「 out_past_post() 」を追加

functions.phpに以下の関数を追加してください。この記事の最後に解説を記載しています。

/**
 * 過去の関連記事一覧の出力
 */
function out_past_posts() {

  global $post;
  if (empty($post)) {
    return;
  }

  // 投稿日
  $date = get_post_datetime($post);
  $date_format = 'Y/m/d H:i:s';
  $date_published_str = $date->format($date_format);

  // カテゴリー一覧
  $categories = get_the_category();
  $category_ids = array();
  $ex_cats_param = '2,72,74'; // 除外カテゴリー
  $ex_cats = explode(',', $ex_cats_param);
  foreach( $categories as $category ) {
    if( !in_array($category->cat_ID, $ex_cats) ) {
      array_push( $category_ids, $category->cat_ID );
    }
  }

  // 記事一覧取得
  $args = array(
    'post_type' => 'post',
    'post_status' => 'publish',
    'category__in' => $category_ids,
    'date_query' => array(
      array(
        'before'     => $date_published_str,
        'inclusive' => false,
      ),
    ),
    'orderby' => 'date',
    'order' => 'DESC',
    'posts_per_page' => 10,
  );
  $my_query = new WP_Query( $args );

  // 出力
  if ( $my_query -> have_posts() ) : ?>
    <ul class="wp-block-latest-posts__list wp-block-latest-posts">
    <?php while ( $my_query -> have_posts() ) : $my_query -> the_post(); ?>
      <li>
        <div class="wp-block-latest-posts__featured-image alignleft">        
        <?php the_post_thumbnail( 'medium', array( 'alt' => the_title_attribute( 'echo=0' ) ) ); ?>
        </div>
        <a href="<?php the_permalink() ?>"><?php the_title_attribute(); ?></a>
      </li>
    <?php endwhile; wp_reset_query(); ?>
    </ul>
  <?php endif;
}
add_shortcode('past_posts', 'out_past_posts');

ショートコード

[past_posts]

ショートコードはこれだけです。
カテゴリー指定や、除外カテゴリーなどのパラメーターが設定できるようにしても便利そうですね。

ポイント

引数の渡し方など詳しい仕様は「WordPress公式のドキュメント」をご確認ください。
WordPress公式「ショートコード」ドキュメントはこちら

プログラムの解説

ブロックごとにプログラムの解説を記載しました。

記事の投稿日を取得

  // 投稿日
  $date = get_post_datetime($post);
  $date_format = 'Y/m/d H:i:s';
  $date_published_str = $date->format($date_format);

get_post_datetime()で取得した投稿日を、format()関数で「 YYYY/mm/dd HH:MM:SS 」形式の文字列に変換します。

記事のカテゴリー一覧を取得

  // カテゴリー一覧
  $categories = get_the_category();
  $category_ids = array();
  $ex_cats_param = '2,72,74'; // 除外カテゴリー
  $ex_cats = explode(',', $ex_cats_param);
  foreach( $categories as $category ) {
    if( !in_array($category->cat_ID, $ex_cats) ) {
      array_push( $category_ids, $category->cat_ID );
    }
  }

get_the_category()で取得したカテゴリーオブジェクトの配列をループしながら $category_ids 配列に追加していきます。その際、特定のカテゴリーを除外するようにしています。

記事一覧の取得

 // 記事一覧取得
 $args = array(
    'post_type' => 'post', ←投稿を対象
    'post_status' => 'publish', ←公開中を対象
    'category__in' => $category_ids, ←カテゴリーID
    'date_query' => array(
      array(
        'before'     => $date_published_str, ←投稿日より前
        'inclusive' => false, ←指定の日を含むかどうか
      ),
    ),
    'orderby' => 'date',   ←投稿日で並び替え
    'order' => 'DESC',  ←降順で並び替え
    'posts_per_page' => 10, ←取得記事数
  );
  $my_query = new WP_Query( $args );

WP_Query ()で、現在の記事より過去の記事一覧を投稿日の降順で先頭の10件を取得するようにしています。ソースコード上の説明も参考にしてください。

ポイント

記事一覧の取得はquery_posts()は非推奨となっています。WP_Query()または、get_posts()を使いましょう。
WP_Query()のWordPress公式ドキュメントはこちら

出力

  // 出力
  if ( $my_query -> have_posts() ) : ?>
    <ul class="wp-block-latest-posts__list wp-block-latest-posts">
    <?php while ( $my_query -> have_posts() ) : $my_query -> the_post(); ?>
      <li>
        <div class="wp-block-latest-posts__featured-image alignleft">
        <?php the_post_thumbnail( 'medium', array( 'alt' => the_title_attribute( 'echo=0' ) ) ); ?>
        </div>
        <a href="<?php the_permalink() ?>"><?php the_title_attribute(); ?></a>
      </li>
    <?php endwhile; wp_reset_query(); ?>
    </ul>
  <?php endif;

WordPressのブロックエディタの「最新の投稿」と同じHTML構造にしています。画像部分は「medium」になっていますので希望のサイズに変更してください。

the_post_thumbnail(); // パラメータなし -> 'post-thumbnail'
the_post_thumbnail( 'thumbnail' ); // サムネイル (デフォルト 150px x 150px :最大値)
the_post_thumbnail( 'medium' ); // 中サイズ (デフォルト 300px x 300px :最大値)
the_post_thumbnail( 'large' ); // 大サイズ (デフォルト 640px x 640px :最大値)
the_post_thumbnail( 'full' ); // フルサイズ (アップロードした画像の元サイズ)
the_post_thumbnail( array( 100, 100 ) ); // 他のサイズ

WordPress Codex

ポイント

wp_reset_query()は、WP_Query()とセットでループの終了後に実行が必要です。

まとめ

以上、WordPressの関連記事で過去の記事だけを表示する方法のご紹介でした。WP_Query()はたくさんの仕様があるので一つマスターしたらさまざまな応用ができるようになると思います。 是非マスターしてくださいね!