カスタムフィールドの日付フィールドで年毎に折りたたみ可能な月別リストとアーカイブページを作成
カテゴリー: WordPress
イベント等の開催日を Advanced Custom Fields (ACF) の日付選択フィールドで作成し、この開催日をを使って年月別のアーカイブページを作りたい。そして更に、その月別リストを年単位で開閉表示させたいと考えました。
通常の月別アーカイブの月別リストを年単位で開閉表示させる方法は、「WordPressの月別アーカイブを年単位で開閉させる *Ateitexe」に書かれていましたので、これを参考にさせていただきました。
一方、カスタムフィールドの日付から月別アーカイブを作成する方法は、「カスタムフィールドに入力した日付で月別絞り込み&アーカイブページの整形 | oku-log」等で説明されていますが、今回は月別リストの開閉表示をしたかったので、オリジナルで実装してみることにしました。
まず前提として、カスタムフィールドの年月別のページは日付アーカイブを使わず、固定ページで作成して、URL パラメータを使って対象のイベントの一覧を取得することにします。
https://example.com/event/monthly/?date=202403
のような URL として、date パラメータの値と日付フィールドの値(Ymd の Ym または Y)が一致するイベントを抽出するという感じです。
開閉式月別リストの作成
「WordPressの月別アーカイブを年単位で開閉させる *Ateitexe」で紹介されているコードを元に、対象を投稿日から日付カスタムフィールドの値に置き換えます。ついでに、表示している月にスタイルを当てるために class="current-date"
を付与し、開閉ボタンのタグをキーボード操作が可能な button
要素に変更しました。
イベントはカスタム投稿タイプ “event” とし、イベント開催日の日付フィールドの名前は “event_date” としています。
<ul>
<?php
$current_date = '';
$current_year = '';
if ( is_page('monthly') ){
$current_date = $_GET['date']; // 表示しているページの年月を取得
$current_year = substr($current_date, 0, 4); // 表示しているページの年を取得
}
?>
<ul class="accordion">
<?php
$y_flg = true; //年の切替フラグ
$f_flg = true; //初回フラグ
$year = idate('Y')+1; //翌年までのイベントを取得
$month = 12; //12月までイベントを取得
$oldest_year = 2023; //一番古いイベントの年
while ( $year >= $oldest_year ) { //一番古いイベント年を指定年が下回るまでループ
//年見出し出力
if ( $y_flg == true ){ //年切替フラグが立っていたら
//指定年のイベント数を取得
$args = array(
'post_type' => 'event',
'meta_query' => array(
array(
'key' => 'event_date',
'value' => $year,
'compare' => 'LIKE',
)
),
'post_status' => 'publish',
'posts_per_page' => -1
);
$my_query = new WP_Query( $args );
$year_archives_num = $my_query->post_count;
if ( $year_archives_num > 0 ){ //指定年のイベントがあったら閉じた年見出しを出力
if ( $f_flg == true ){ //初回は閉じタグ不要&開いておく
?>
<li>
<div<?php if ( $year == $current_date ){ echo ' class="current-date"'; } ?>>
<?php
if ( !is_page('monthly') || (is_page('monthly') && $year == $current_year) ){
echo '<button aria-label="月リストを開く" aria-expanded="true" class="open"></button>';
} else {
echo '<button aria-label="月リストを開く" aria-expanded="false"></button>';
}
?><a href="<?php echo home_url().'/event/monthly/?date='.$year; ?>"><?php echo $year; ?>年 (<?php echo $year_archives_num; ?>)</a>
</div>
<ul<?php if ( is_page('monthly') && $year != $current_year ){ echo ' style="display: none;"'; } ?>>
<?php
$f_flg = false; //1度通ったらフラグを倒しておく
} else { //2回目以降は閉じタグ必要&閉めておく
?>
</ul>
</li>
<li>
<div<?php if ( $year == $current_date ){ echo ' class="current-date"'; } ?>>
<?php
if ( is_page('monthly') && $year == $current_year ){
echo '<button aria-label="月リストを開く" aria-expanded="true" class="open"></button>';
} else {
echo '<button aria-label="月リストを開く" aria-expanded="false"></button>';
}
?><a href="<?php echo home_url().'/event/monthly/?date='.$year; ?>"><?php echo $year; ?>年 (<?php echo $year_archives_num; ?>)</a>
</div>
<ul<?php if ( !is_page('monthly') || (is_page('monthly') && $year != $current_year) ){ echo ' style="display: none;"'; } ?>>
<?php
}
$y_flg = false; //年見出しが出力されたら年切替フラグを倒しておく
} else { //該当の年にイベントがなかった場合
$year--; //1年前へ
$month = 12; //12月へ
}
}
//月アーカイブ出力
if ( $y_flg == false ){ //年切替フラグが倒れていたら
//指定年月のイベント数を取得
$args = array(
'post_type' => 'event',
'meta_query' => array(
array(
'key' => 'event_date',
'value' => $year.sprintf('%02d',$month),
'compare' => 'LIKE',
)
),
'post_status' => 'publish',
'posts_per_page' => -1
);
$my_query = new WP_Query( $args );
$month_archives_num = $my_query->post_count;
if ( $month_archives_num > 0 ) { //指定年月のイベントがあったらアーカイブリンクを出力
?>
<li><a href="<?php echo home_url().'/event/monthly/?date='.$year.sprintf('%02d',$month); ?>"><?php echo $year; ?>年<?php echo $month; ?>月 (<?php echo $month_archives_num; ?>)</a></li>
<?php
}
$month--; //1月前へ
if ( $month < 1 ){ //0月になってしまったら
$year--; //1年前へ
$month = 12; //12月へ
$y_flg = true; //年切替フラグを立てる
}
}
}
?>
</ul>
</li>
</ul>
通常の月別アーカイブと異なる点として、$year
と $month
に代入するは本日の年と月ではなく、本日の翌年と12月としています。通常の投稿日の月別アーカイブは本日までをリスト化すればよいですが、イベント開催日の場合は未来の日付も存在するからです。
また、年毎あるいは月毎の投稿数(イベント数)を取得するために、WP_Query を使い、日付フィールドの値で抽出しています。
あと、それぞれの月のリンク先は、固定ページの URL に date パラメータを追記しています。
jQuery と CSS は省略します。
年月毎のイベントアーカイブページの作成
年月毎のアーカイブページは固定ページを使用します。イベントのメインページの子ページとして mothly というスラッグで作成しましたので、page-monthly.php というテーマファイルを作成し、イベントリストの出力箇所に以下のように記述します。
<?php if ( isset($_GET['date']) ){ $this_month = $_GET['date']; } ?>
<h2><?php echo substr($this_month, 0, 4). '年';
if ( substr($this_month, 4, 2) ){
echo sprintf('%d', substr($this_month, 4, 2)). '月';
} ?>開催のイベント</h2>
<?php
$args = array(
'post_type' => 'event',
'meta_query' => array(
array(
'key' => 'event_date',
'value' => $this_month,
'compare' => 'LIKE',
)
),
'orderby' => 'meta_value',
'order' => 'ASC',
'post_status' => 'publish',
'paged' => $paged,
'posts_per_page' => 10
);
$my_query = new WP_Query( $args );
if ( $my_query -> have_posts() ):
echo '<ul class="archiveList eventList">'. "\n";
while ( $my_query -> have_posts() ): $my_query -> the_post();
(イベントリストの出力)
endwhile;
echo '</ul>'. "\n";
else:
echo '<p class="noInfo">該当のイベントはありません。</p>'. "\n";
endif;
wp_reset_postdata();
?>
URL の date パラメータの値と日付フィールドの値の年月または年が一致するイベントを抽出しています。URL パラメータを使うことにより、固定ページを使ってアーカイブページのように振る舞うことができます。
イベント開催日が複数日に渡る場合
上記は単純にイベント開催日が単独の1日の場合ですが、実際には2日間以上に渡ったり、離れた複数の日に開催され、月が跨ることもあります。このような場合、それぞれの月に表示する必要があります。
私の場合、ACF の繰り返しフィールドを使い、開始日と終了日のセットを繰り返し設定できるようにしています。
繰り返しフィールドの名前を event_dates、サブフィールドの開始日を event_start、終了日を event_end とします。
まず、WP_Query を繰り返しフィールドで絞り込むことができるように functions.php に以下を追記します。
function my_posts_where_subfield($where, $query) {
if ($query->get('subfield_meta_key')) {
$where = str_replace('meta_key =', 'meta_key LIKE', $where);
}
return $where;
}
add_filter('posts_where', 'my_posts_where_subfield', 10, 2);
月別リストの該当箇所を次のように置き換えます。
//指定年のイベント数を取得
$args = array(
'post_type' => 'event',
'subfield_meta_key' => true,
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'event_dates_%_event_start',
'value' => $year,
'compare' => 'LIKE',
),
array(
'key' => 'event_dates_%_event_end',
'value' => $year,
'compare' => 'LIKE',
)
),
'post_status' => 'publish',
'posts_per_page' => -1
);
//指定月のイベント数を取得
$args = array(
'post_type' => 'event',
'subfield_meta_key' => true,
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'event_dates_%_event_start',
'value' => $year.sprintf('%02d',$month),
'compare' => 'LIKE',
),
array(
'key' => 'event_dates_%_event_end',
'value' => $year.sprintf('%02d',$month),
'compare' => 'LIKE',
)
),
'post_status' => 'publish',
'posts_per_page' => -1
);
アーカイブページ(固定ページ)の該当箇所は以下です。
$args = array(
'post_type' => 'event',
'subfield_meta_key' => true,
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'event_dates_%_event_start',
'value' => $this_month,
'compare' => 'LIKE',
),
array(
'key' => 'event_dates_%_event_end',
'value' => $this_month,
'compare' => 'LIKE',
)
),
'orderby' => 'meta_value',
'order' => 'ASC',
'post_status' => 'publish',
'paged' => $paged,
'posts_per_page' => 10
);
以上で理想のカタチで開催年月のアーカイブページを出力することができました。
あとは、アーカイブページの title 属性やパンくずリストが固定ページのタイトルになりますので、表示しいている年月に置き換える処理など、細々とした調整を行なっています。