月ごとのイベント開催カレンダーとかにありがちなやつを作りました。
仕様
ワイヤーフレーム
投稿一覧
- [月別インデックス]をクリックするとその月が[日程]に含まれる投稿がタブ切り替え方式で表示される
- [日程]は、[開始日][終了日]で設定されている。[開始日]のみの投稿もある。
- 今日以降の[日程]が含まれた投稿が表示される
- 投稿はカスタム投稿タイプで作成する
実装
カスタム投稿タイプ
一般的な方法で作成済みとします。説明は割愛。
スラッグは、"events"にしました。
カスタムフィールドを作成
- 開始日
- [フィールドタイプ]…[デイトピッカー]
- [返り値のフォーマット]…[Custom] → "Y-m-d"
- 終了日
- 開始日と同じ
- 但し[必須か?]は[いいえ]にする(開始日のみの投稿もあるので)
テンプレートファイル
archive.php
<?php
$today = date('Y-m-d');
// $today = date("Y-m-d", strtotime('2020-01-31')); //for debug
$args = array(
'post_type'=> 'events',
'orderby' => 'meta_value',
'order' => 'ASC', //昇順
'meta_key' => 'evstartdate', //ACFのフィールド名
'meta_query' => array( // 判定条件…(開始日 >= 今日)or(終了日 >= 今日)
'relation' => 'OR',
array(
'key' => 'evstartdate',
'value' => $today,
'type' => 'date',
'compare' => '>=',
),
array(
'key' => 'evenddate',
'value' => $today,
'type' => 'date',
'compare' => '>=',
),
),
'posts_per_page' => 0,
);
$query = new WP_Query( $args );
if( $query->have_posts() ) :
/*================================
月別投稿リスト取得
=================================*/
while ( $query->have_posts() ) : $query->the_post();
$date1 = date('Y-m-d',strtotime(get_field('evstartdate', false, false)));
if ( get_field('evenddate') ) {
// 終了日が設定されている場合
$date2ym = date('Y-m',strtotime(get_field('evenddate', false, false)));
// 開始日が今日より前・・今日の月~終了月を設定
// 開始日が今日以降・・・開始日月~終了月を設定
$tmpdate = ( $today > $date1 ) ? $today : $date1;
while( $date2ym >= date("Y-m", strtotime($tmpdate)) ) {
$eventlist[ date("Y-m", strtotime($tmpdate)) ][] = get_the_ID();
$tmpdate = date("Y-m-1", strtotime($tmpdate));//月はじめに変換(31日等の場合に月を飛び越える事を防ぐため)
$tmpdate = date("Y-m-d",strtotime($tmpdate . "+1 month"));//1ヶ月後の月を取得
}
} else {
// 終了日が未設定の場合は、開始日の月のみ設定
$eventlist[ date("Y-m", strtotime($date1)) ][] = get_the_ID();
}
endwhile;
// echo '<pre>';var_dump($eventlist); echo '</pre>';
if( isset($eventlist) ) :
/*================================
月インデックス出力
=================================*/
?>
<div class="month-index">
<ul>
<?php
foreach( $eventlist as $ym => $archive ) :
$ym_arr = explode( '-', $ym );
echo '<li>' . $ym_arr[0].'年'.$ym_arr[1].'月</li>'; // 月インデックス出力
endforeach;
?>
<?php wp_reset_postdata(); //必須 ?>
</div>
<div class="month-content">
<div class="active">
<?php
/*================================
月別投稿リスト出力
=================================*/
foreach ($eventlist as $value) :
$args = array(
'post_type' => 'events',
'post__in' => $value,
'posts_per_page' => 0,
);
$query = new WP_Query( $args );
?>
<ul class="ls-reports">
<?php while ( $query->have_posts() ) : $query->the_post(); ?>
<?php
/*================================
投稿の内容を出力します!
=================================*/
?>
<?php endwhile; ?>
</ul>
</div>
<div>
<?php
wp_reset_postdata(); //必須
endforeach;
?>
</div>
</div>
<?php else : ?>
<p style="text-align:center">実施予定は調整中です。</p>
<?php endif; ?>
<?php else : ?>
<p style="text-align:center">現在、開催予定のイベントはありません。</p>
<?php endif; ?>
タブ切り替え処理
js
jQuery(function($){
// 月別投稿 タブ切り替え
var $index = $('.month-index li');
var $content = $('.month-content > div');
$index.eq(0).addClass('active');
$content.eq(0).addClass('active');
$index.click(function(){
$index.removeClass('active');
$(this).addClass('active');
$content.removeClass('active');
$content.eq($(this).index()).addClass('active');
});
});
SASS
※タブ切り替えに関わる部分のみ
.month-index {
ul {
display: flex;
flex-wrap: wrap;
li {
flex: 0 1 29%;
}
}
}
.month-content {
> div {
display: none;
&.active {
display: block;
}
}
}
説明
タブ切り替えを踏まえ、以下のようなhtmlを作ることにする。
<div class="month-index">
<ul>
<li>2020年1月</li>
<li>2020年2月</li>
</ul>
</div>
<div class="month-content">
<!-- 2020年1月の投稿 -->
<div>
<ul>
<li>投稿が入ります</li>
<li>投稿が入ります</li>
</ul>
</div>
<!-- 2020年2月の投稿 -->
<div>
<ul>
<li>投稿が入ります</li>
<li>投稿が入ります</li>
</ul>
</div>
</div>
php では、$eventlistがポイント。
$today = date('Y-m-d');
// $today = date("Y-m-d", strtotime('2020-01-31')); //for debug
$args = array(
'post_type'=> 'events',
'orderby' => 'meta_value',
'order' => 'ASC', //昇順
'meta_key' => 'evstartdate', //ACFのフィールド名
'meta_query' => array( // 判定条件…(開始日 >= 今日)or(終了日 >= 今日)
'relation' => 'OR',
array(
'key' => 'evstartdate',
'value' => $today,
'type' => 'date',
'compare' => '>=',
),
array(
'key' => 'evenddate',
'value' => $today,
'type' => 'date',
'compare' => '>=',
),
),
'posts_per_page' => 0,
);
$query = new WP_Query( $args );
if( $query->have_posts() ) :
/*================================
月別投稿リスト取得
=================================*/
while ( $query->have_posts() ) : $query->the_post();
$date1 = date('Y-m-d',strtotime(get_field('evstartdate', false, false)));
if ( get_field('evenddate') ) {
// 終了日が設定されている場合
$date2ym = date('Y-m',strtotime(get_field('evenddate', false, false)));
// 開始日が今日より前・・今日の月~終了月を設定
// 開始日が今日以降・・・開始日月~終了月を設定
$tmpdate = ( $today > $date1 ) ? $today : $date1;
while( $date2ym >= date("Y-m", strtotime($tmpdate)) ) {
$eventlist[ date("Y-m", strtotime($tmpdate)) ][] = get_the_ID();
$tmpdate = date("Y-m-1", strtotime($tmpdate));//月はじめに変換(31日等の場合に月を飛び越える事を防ぐため)
$tmpdate = date("Y-m-d",strtotime($tmpdate . "+1 month"));//1ヶ月後の月を取得
}
} else {
// 終了日が未設定の場合は、開始日の月のみ設定
$eventlist[ date("Y-m", strtotime($date1)) ][] = get_the_ID();
}
endwhile;
上記で以下のような配列を作成し、それをもとに月別インデックスと、月別の投稿一覧を生成する。
array(5) {
["2019-05"]=>
array(1) {
[0]=>
int(2303)
}
["2019-06"]=>
array(1) {
[0]=>
int(2303)
}
["2019-09"]=>
array(2) {
[0]=>
int(2302)
[1]=>
int(2301)
}
["2019-12"]=>
array(3) {
[0]=>
int(2318)
[1]=>
int(2328)
[2]=>
int(2329)
}
["2020-03"]=>
array(1) {
[0]=>
int(2339)
}
}
おわり
もっとスマートな方法があれば教えて下さい。
参考サイト
【WordPress】wp_get_archivesを使わずに特定カテゴリーの年月アーカイブリストを表示したい
https://www.rcnt.jp/blog/wordpress-wp_get_archives/