年度アーカイブのリンクを出力する方法【WordPress】

※本ブログの目的は個人の備忘録であり、コードは参考用として掲載しています。
実際に使用される際は、ご自身の環境で十分に動作確認を行ってください。
コードの利用によって生じたいかなる問題についても責任を負いかねますので、あらかじめご了承ください。

はじめに

WordPressで「年度(会計年度など)」ごとのアーカイブリンクを作成したい場合、単純に西暦年(1月〜12月)で分類するだけでは要件を満たせないことがあります。
特に、日本のように「4月始まりの年度区切り」で投稿をまとめたいケースは多く見られます。

しかし、WordPressのアーカイブリンクを取得する関数 wp_get_archives'type' => 'yearly' を指定すると、暦年(1月〜12月)ベースのアーカイブリンクしか出力されません。

たとえば、2024年3月1日に公開した記事は「2023年度(2023年4月〜2024年3月)」に含めたいところですが、wp_get_archives はこれを「2024年の投稿」として扱うため、2023年度としてリンクが出力されないという問題が発生します。(特にその年度に1件しか投稿がない場合、アーカイブリンク自体が出力されません)

それでは、どうすれば「4月始まりの年度」でアーカイブリンクを正しく出力できるのか?
この記事では、年度単位のアーカイブリンクを動的に出力する方法を、実際のコードとあわせて丁寧に解説します。

年度アーカイブについて

年度アーカイブリンクの出力の前に、まず「年別アーカイブ」を「年度アーカイブ」に修正する必要があります。
例えば「2023年度 = 2023年4月1日〜2024年3月31日」など、暦年ではなく会計年度や学校年度の区切りで投稿をグループ化する方法です。

WordPressのデフォルトの年別アーカイブは暦年ベースなので、カスタマイズが必要です。

実際に年別アーカイブを年度アーカイブに修正するコードはここでは割愛させていただきます。
pre_get_postsを利用してループ前に年度の範囲を修正するというやり方で可能で、以下の記事を参考にさせていただきました。
WordPress の年別アーカイブを年度別(4月はじまり)にカスタマイズする方法。

実装のポイント

それでは、年度アーカイブリンクの出力方法について解説していきます。

投稿を全件取得して年度ごとに分類する方法も考えられますが、年単位のアーカイブを出力したいということは、ある程度記事数が多いケースが想定されます。
そのため、パフォーマンスへの影響を最小限に抑えるために、ここでは 各年度ごとに「投稿が1件でも存在するか」をチェックするだけの方法を採用します。

この方法なら、各年度に対して軽量なクエリを1回ずつ実行するだけで済むため、全件取得に比べて負荷を抑えつつ、必要な年度リンクだけを表示することができます。

まずは最古の投稿をもとにどの年度からリンクを表示するべきかを判断し、その後、現在の年まで各年度に該当する投稿があるかを確認してリンクを出力します。

1. 最古の投稿を取得する

まず、年度リンクを作成する際に「どの年度から開始するべきか」を判断します。

そのために、まず最古の投稿を取得します。これ以降の処理は、投稿がある場合のみ実行します。

// 年度別アーカイブリンク
$oldest_post = get_posts(array( // 最古の投稿年を取得
  'post_type'      => 'news',
  'posts_per_page' => 1,
  'orderby'        => 'date',
  'order'          => 'ASC',
  'fields'         => 'ids',
  'post_status'    => 'publish',
));

if (!empty($oldest_post)) {
  // 投稿が存在する場合は、処理を行う(2以降のコードはこの中にいれる)
}

2. 最古の投稿年度を計算する

重要なのは、最古の投稿が含まれる年度(4月始まり)を正しく把握することです。

たとえば、2025年3月31日に投稿された記事は「2024年度(2023年4月〜2024年3月)」に含まれます。このように、最古の投稿が3月など年度末の日付であっても、その投稿が属する年度を正確にカバーする必要があります。

そのため、$start_year最古の投稿が属する年度を含められるように、さらに1年さかのぼって計算します。

例:最古の投稿が「2025/03/31」の場合 →「2024年度」に属する → 「2023年度」から表示開始。

このようにして、年度の境目にある投稿も確実に取得できるよう、安全のため1年余裕を持たせています。

// 最古の投稿の投稿日時を取得
$oldest_post_id = $oldest_post[0];
$timestamp = get_post_time('U', true, $oldest_post_id);
$year = (int) date('Y', $timestamp);
$month = (int) date('n', $timestamp);

// 年度開始年を計算(4月始まり+1年余分にさかのぼる)
$start_year = ($month < 4) ? $year - 2 : $year - 1;

3. 年度ごとに投稿の存在をチェックしてリンクを出力する

次に、現在の年から先ほど調べた $start_year まで遡って、各年度に投稿が存在するかを確認します。

$current_year = (int)date('Y');

echo '<ul class="year-list">';

for ($y = $current_year; $y >= $start_year; $y--) { // 現在の年から最古の投稿年まで、年度を1つずつ調べる
  $after  = "$y-04-01";
  $before = ($y + 1) . "-03-31 23:59:59";

  $query = new WP_Query(array(
    'post_type'      => 'news',
    'posts_per_page' => 1,
    'post_status'    => publish',
    'date_query'     => array(array(
      'after'     => $after,
      'before'    => $before,
      'inclusive' => true,
    )),
    'fields' => 'ids',
  ));

  if ($query->have_posts()) {
    echo '<li><a href="' . home_url('/news/' . $y) . '">' . $y . '年度</a></li>';
  }
  wp_reset_postdata();
}

echo '</ul>';

ポイント

  • 年度は「4月1日〜翌年3月31日」として定義
  • 最古の投稿の公開月によって、さらに1年度前まで遡る必要がある
  • 各年度に1件でも投稿があれば、アーカイブリンクを出力
  • posts_per_page を1件にし、軽量な存在チェックを行う

まとめ

  • WordPressの年別アーカイブは暦年ベースだが、会計年度や学校年度に合わせて出力するにはカスタマイズが必要
  • 最古の投稿を基準に、年度の境界(4月)を考慮して適切な開始年度を決定
  • 各年度に対して軽量なクエリで投稿の有無を確認し、存在する年度のみリンクを出力
  • パフォーマンスにも配慮した実装で、将来の投稿にも柔軟に対応可能

参考コードまとめ

// 最古の投稿を取得
$oldest_post = get_posts(array(
  'post_type'      => 'news',
  'posts_per_page' => 1,
  'orderby'        => 'date',
  'order'          => 'ASC',
  'fields'         => 'ids',
  'post_status'    => 'publish',
));

if (!empty($oldest_post)) {
  // 最古の投稿日時を取得
  $oldest_post_id = $oldest_post[0];
  $timestamp = get_post_time('U', true, $oldest_post_id);
  $year = (int) date('Y', $timestamp);
  $month = (int) date('n', $timestamp);

  // 年度開始年を計算(4月始まり+1年余分にさかのぼる)
  $start_year = ($month < 4) ? $year - 2 : $year - 1;

  // 現在の年
  $current_year = (int) date('Y');

  echo '<ul class="year-list">';
  for ($y = $current_year; $y >= $start_year; $y--) {
    $after  = "$y-04-01";
    $before = ($y + 1) . "-03-31 23:59:59";

    $query = new WP_Query(array(
      'post_type'      => 'news',
      'posts_per_page' => 1,
      'post_status'    => 'publish',
      'date_query'     => array(array(
        'after'     => $after,
        'before'    => $before,
        'inclusive' => true,
        'column'    => 'post_date',
      )),
      'fields' => 'ids'
    ));

    if ($query->have_posts()) {
      echo '<li><a class="js-cat" href="' . home_url('/news/' . $y) . '">' . $y . '</a></li>';
    }
    wp_reset_postdata();
  }
  echo '</ul>';
}

参考

WordPress の年別アーカイブを年度別(4月はじまり)にカスタマイズする方法。
WordPress 年別アーカイブリストの表示方法 - by Takumi Hirashima
wp_get_archives() – Function | Developer.WordPress.org