WordPressで年別なら、下記の方法でアーカイブリスト(一覧)が作れます。
でも年度別はできません。
<?php $args = array( 'type' => 'yearly', 'limit' => '', 'format' => 'html', 'before' => '', 'after' => '', 'show_post_count' => false, 'echo' => 1, 'order' => 'DESC', 'post_type' => 'news', ); wp_get_archives( $args );
また、カスタム投稿の複数指定はできません。
wp_get_archivesがpost_typeの配列を受け入れないので。
色々とテストしたけど、どれもダメ。。。
結果、カスタム投稿を辞めて、投稿+カテゴリにしました。
結論:固定ページを使う
通常アーカイブで使うテンプレート archive.php date.php などではダメ。
4月切り替えの年度で、2020年4月~12月までの記事がなく、2021年1月~3月までの記事のみある場合、404エラーになるから。
まず、本文なしの固定ページ(スラッグnews)を作って、固定ページ用のテンプレートを作ります。
page.php やら index.php ですね。
そこに、下記をぶち込みます。
// 表示中の年を入れる.
$years = null;
// URLのgetから呼び出す年度をget.
if ( isset( $_GET['ye'] ) ) {
$years = intval( $_GET['ye'] );
} else {
// 今日の年を整数にして入れる.
$years = intval( date_i18n( 'Y' ) );
// 今日の月を整数にして入れる.
$today_month = intval( date_i18n( 'm' ) );
// 3月までは前年に戻す
if ( 4 > $today_month ) {
$years = ( $years - 1);
}
}
echo '<div>' . esc_html( $years ) . '年度</div>';
// 翌年を定義.
$next_y = ( $years + 1 );
$args = array(
'post_type' => 'post',
// 公開されたものだけ表示.
'post_status' => array( 'publish' ),
// 1ページに含める投稿数(-1を指定すると全投稿を表示)
'posts_per_page' => -1,
// 昇順'ASC'、降順'DESC'.
'order' => 'DESC',
// 投稿順に表示.
'orderby' => 'date',
'date_query' => array(
array(
'after' => array(
// その年の4/1から.
'year' => $years,
'month' => 4,
'day' => 1,
),
'before' => array(
// 翌年の3/31まで.
'year' => $next_y,
'month' => 3,
'day' => 31,
),
'inclusive' => true,
'compare' => 'BETWEEN',
),
),
);
// クエリ定義.
$the_query = new WP_Query( $args );
// ループ.
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
// ループ内記述 この例では別ファイルを用意して読み込み.
include __DIR__ . '/card/card-news.php';
}
} else {
echo '<p>お知らせはありません。</p>';
}
// ループ終わり.
// 投稿データのリセット.
wp_reset_postdata();
// ここから年度別一覧.
<ul>
<?php
$archives = get_archives_by_fiscal_year();
foreach ( $archives as $archive ) {
// https://aw1.jp/wordps/news/?ye=表示年 というようなリンクをつくります
?>
<li><a href="<?php echo esc_url( get_home_url( null, '/news' ) ) . '/?ye=' . esc_html( $archive->year ); ?>"><img src="<?php echo esc_url( get_home_url( null, '/img/menu_o.svg' ) ); ?>"><?php echo esc_html( $archive->year ); ?>年度</a></li>
<?php
}
?>
</ul>
注意!
WordPressのGETパラメータに引っかかるので、リンクを~~/?year=2021 のようにすると、エラーになります。
なので~~/?ye=2021にしました。
function.php に入れ込むもの
上のコードにある
get_archives_by_fiscal_year
これの定義をfunction.phpでします。
/**
* 年度別アーカイブリスト
*
* @param string $args .
*/
function get_archives_by_fiscal_year( $args = '' ) {
global $wpdb, $wp_locale;
$defaults = array (
'post_type' => 'post',
'limit' => '',
'format' => 'html',
'before' => '',
'after' => '',
'show_post_count' => false,
'echo' => 1,
);
$rrr = wp_parse_args( $args, $defaults );
extract ( $rrr, EXTR_SKIP );
if ( '' !== $limit ) {
$limit = absint( $limit );
$limit = ' LIMIT ' . $limit;
}
$arcresults = (array) $wpdb->get_results(
"SELECT YEAR(ADDDATE(post_date, INTERVAL -3 MONTH)) AS `year`, COUNT(ID) AS `posts`
FROM $wpdb->posts
WHERE post_type = '$post_type' AND post_status = 'publish'
GROUP BY YEAR(ADDDATE(post_date, INTERVAL -3 MONTH))
ORDER BY post_date DESC
$limit"
);
return $arcresults;
}
これはhttps://www.webopixel.net/wordpress/871.htmlをそのまま使わせていただきました。
ありがとうございます。
2026年3月版
基本的には、上の考え方 「URLのパラメータ(?ye=)を使ってWordPressの標準バグを回避する」という一番重要なコアのアイデアは全く同じですが、改善したコードを記載します。
WordPress標準のフック pre_get_posts を使う
pre_get_postsとは、メインクエリがデータベースに問い合わせる直前にフック(割り込み)して、クエリの条件を書き換えるアクションフックです。
/**
* URLのパラメータに独自の「ye」を使えるように登録
*/
add_filter(
'query_vars',
function ( $vars ) {
$vars[] = 'ye';
return $vars;
}
);
/**
* カスタムパーマリンクルール
*
* @return void
*/
function add_pastnews_archive_rewrite_rules() {
// URLが /pastnews/2025/ の時、裏側では ye=2025 として処理する
add_rewrite_rule(
'^pastnews/([0-9]{4})/?$',
'index.php?post_type=post&ye=$matches[1]',
'top'
);
// 2ページ目以降用
add_rewrite_rule(
'^pastnews/([0-9]{4})/page/([0-9]+)/?$',
'index.php?post_type=post&ye=$matches[1]&paged=$matches[2]',
'top'
);
}
add_action( 'init', 'add_pastnews_archive_rewrite_rules' );
/**
* データベースから投稿がある年度(4月〜翌3月)を取得し、
* 年度別アーカイブのリンク一覧(HTML)を生成します。
* 結果はキャッシュされ、データベースへの負荷を軽減します。
*
* @return string 年度別リンクのHTMLリスト(<ul>...</ul>形式)
*/
function get_fiscal_year_archives_links() {
// 1. キャッシュ(一時保存データ)が存在するか確認
$html = get_transient( 'fiscal_year_archives_html' );
// 2. キャッシュがない場合のみ、データベースにアクセスして作成する
if ( false === $html ) {
global $wpdb;
// データベースから取得(キャッシュ警告などは解決済みのため無視)
// WordPressの標準関数では対応できない独自の計算のため、直接アクセスを許可するコメント
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$years = $wpdb->get_col(
$wpdb->prepare(
"SELECT DISTINCT IF( MONTH(post_date) >= 4, YEAR(post_date), YEAR(post_date) - 1 ) AS fiscal_year FROM {$wpdb->posts} WHERE post_type = %s AND post_status = %s ORDER BY fiscal_year DESC",
'post',
'publish'
)
);
$html = '<ul>';
if ( ! empty( $years ) ) {
foreach ( $years as $year ) {
$link = home_url( '/pastnews/' . $year . '/' );
$html .= '<li><a href="' . esc_url( $link ) . '">' . esc_html( $year ) . '年度</a></li>';
}
}
$html .= '</ul>';
// 作成したHTMLをキャッシュとして保存(例:1日間 = DAY_IN_SECONDS)
set_transient( 'fiscal_year_archives_html', $html, DAY_IN_SECONDS );
}
return $html;
}
/**
* 記事が投稿・更新・削除された時に、年度別アーカイブの古いキャッシュを削除します。
*
* @param int $post_id 投稿ID
* @return void
*/
function clear_fiscal_year_archives_cache( $post_id ) {
// 自動保存などの場合は処理をスキップして負荷を減らす
if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) {
return;
}
// キャッシュを削除
delete_transient( 'fiscal_year_archives_html' );
}
// 記事が保存(更新)されたときと、削除されたときにキャッシュクリアの関数を動かす
add_action( 'save_post', 'clear_fiscal_year_archives_cache' );
add_action( 'deleted_post', 'clear_fiscal_year_archives_cache' );
/**
* メインクエリをフックして、年別アーカイブの対象期間を
* 「1月1日〜12月31日」から「4月1日〜翌年3月31日」に変更します。
*
* @param WP_Query $query WordPressのクエリオブジェクト(参照渡し)
* @return void 値は返さず、$query オブジェクトを直接操作します
*/
function modify_year_archive_to_fiscal( $query ) {
// 管理画面やメインループ以外には影響させない
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
// yeパラメータがセットされている時(=年度アーカイブが表示された時)だけ実行
if ( $query->get( 'ye' ) ) {
$year = intval( $query->get( 'ye' ) );
$date_query = array(
array(
'after' => array(
'year' => $year,
'month' => 4,
'day' => 1,
),
'before' => array(
'year' => $year + 1,
'month' => 3,
'day' => 31,
),
'inclusive' => true,
),
);
$query->set( 'date_query', $date_query );
// WordPressに「これは正しい年別アーカイブページだ」と強制的に認識させる
$query->is_archive = true;
$query->is_year = true;
$query->is_home = false;
}
}
add_action( 'pre_get_posts', 'modify_year_archive_to_fiscal' );
/**
* アーカイブページのタイトル出力(the_archive_titleなど)をフックし、
* 年別アーカイブの場合に「〇〇年度のニュース」という表記に変更します。
*
* @param string $title 現在のアーカイブタイトル文字列
* @return string 変更後のアーカイブタイトル文字列
*/
add_filter(
'get_the_archive_title',
function ( $title ) {
$ye = get_query_var( 'ye' );
if ( $ye ) {
$title = $ye . '年度のニュース';
}
return $title;
}
);
archive.php のサイドバーなど、年度別リンクを表示させたい場所に入れる
<section class="archive-year">
<h3>年度別アーカイブ</h3>
<?php echo wp_kses_post( get_fiscal_year_archives_links() ); ?>
</section>
コピペは自由ですが、動作確認をしっかりするようにしてください。


