PHP:カレンダーを作る。複数月表示対応で開始年月も指定できます。
仕事で何度かPHPでカレンダーを作ったのですが、頻繁にあるわけじゃなかったのでその都度考えながら作ってました。
でも一つフォーマットというか関数を作っておけば楽だなぁと思い作ってみました。
どっちかっていうと自分用ですかね。
別途データがを連動させる場合(イベント日時や休日設定等)はこれを改良するって感じですかね。
使い方
今回は使い方から書いていこうかと思います。
自作の関数「create_calendar」を使います。
引数には表示させるカレンダーの数と初めの年月を設定できます。
create_calendar( int:表示させるカレンダーの数, str:初めの年月 )
引数なし
引数を設定しない場合は表示されるカレンダーの数は1、年月は今月になります。
create_calendar()
引数あり
表示されるカレンダーの数を12に設定した場合。
create_calendar( 12 )
今月から12ヶ月分表示します。
表示されるカレンダーの数を12、開始年月を2020年1月に設定した場合。
create_calendar( 12, '2020-1' )
年月は「Y-m」か「Y-n」で指定してください。
設定した年月から12ヶ月分表示します。
関数 create_calendar
function create_calendar( $num = 1, $set = false ) { //今日 $date = new DateTime(); $today = $date->format( 'Y-n-j' ); //最初の月 if( $set ) { $date = new DateTime( $set ); } for( $i = 0; $i < $num; ++$i ) { //描画する月 $month = $date->format( 'Y-n' ); //1ヶ月すすめる $date->modify( '+1 months' ); //年-月の分離 list( $y, $m ) = explode( '-', $month ); //月の初めの曜日 $start_date = new DateTime( 'first day of ' .$month ); $week = $start_date->format( 'w' ); //月の終わりの日 $end_date = new DateTime( 'last day of ' .$month ); $end = $end_date->format( 'j' ); //カレンダーテーブル echo '<table>'; echo '<thead><tr><th colspan="7" class="month">'.$y.'年'.$m.'月</tr></thead>'; echo '<tbody>'; echo '<tr><th>日</th><th>月</th><th>火</th><th>水</th><th>木</th><th>金</th><th>土</th></tr>'; //週の数 $week_line = 0; for( $day = 1; $day <= $end; ++$day ) { //1日、もしくは日曜日 if( $day == 1 || $week == 0 ) { echo '<tr>'; ++$week_line; } //1日かつ日曜日ではない if( $day == 1 && $week != 0 ) { for( $c = 0; $c < $week; ++$c ) { echo '<td class="blank"> </td>'; } } //日 if ( $month.'-'.$day == $today ) { echo '<td><strong>'.$day.'</strong></td>'; } else { echo '<td>'.$day.'</td>'; } //最終日かつ土曜日ではない if( $day == $end && $week != 6 ) { for( $c = $week; $c < 6; ++$c ) { echo '<td class="blank"> </td>'; } } //最終日、もしくは土曜日 if( $day == $end || $week == 6 ) { echo '</tr>'; } //曜日をすすめる if( $week == 6 ) { $week = 0; } else { ++$week; } } //表示するカレンダーが複数かつ週の数が6未満の場合 if( $num != 1 && $week_line < 6 ) { for( $n = $week_line; $n < 6; ++$n ) { echo '<tr>'; for( $c = 0; $c < 7; ++$c ) { echo '<td class="blank"> </td>'; } echo '</tr>'; } } echo '</tbody>'; echo '</table>'; } }
説明
以下、簡単に説明します。
このまま使っても大丈夫ですし、必要であれば変更してください。
見出しはソース内のコメントに対応しています。
最初
引数の初期値を決めておきます。
$numがカレンダーの表示数で初期値が1。
$setが表示されるカレンダーの最初の年月で初期値は無し。
今日・最初の月
まず今日の日付を取得し、変数に入れておきます。
日付の取得はDateTimeクラスを使用しました。
$date->format( ‘Y-n-j’ )で年-月-日の型にして変数に入れておきますす。
次に表示されるカレンダーの最初の月を指定します。
$setに値があればの年月を改めて変数に入れ直します。
値がなければこの処理は行わず、上で取得した今日(今月)を使用します。
for~
$numで設定してある数分カレンダー描画を繰り返します。
描画する月/1ヶ月すすめる/年-月の分離
変数$dateに入れてあるデータから、Y-nで年月のみ取り出しで描画用変数に入れておきます。
$date->modify( ‘+1 months’ )で$dateに入ってる年月を1ヶ月進めておきます。
なので次に$dateから年月を取り出した場合は次の月ということになります。
年-月の分離は表示用です。表示しない場合は必要ないですし、他のやり方でもOK。
月の初めの曜日/月の終わりの日
DateTimeクラスではfirst day ofで月の初日、last day ofで月の最終日のデータが取得できます。
どの月でも初日は1日ですが曜日は違うので、曜日を取得しておきます。
PHPでは曜日は英語表記、もしくは番号です。
この場合は番号で取得しています。
最終日は30日なのか31日なのか、はたまた28日なのかわからないのでその日にちを取得しておきます。
カレンダーテーブル
テーブルのtheadに年月、tbodyの見出しに曜日の名称入れてます。
ここも必要に応じて変更してください。
週の数
月によってカレンダー上に表示される週の数が5だったり6だったりしますので、それを保管しておく変数です。
これは後に使用します。
1日、もしくは日曜日
このカレンダーは日曜日から始まりますので、日曜日で区切りのtrを出力します。
カレンダーの初日は日曜日でなくとも出力します。
このタイミングで上で設定した週の数を増やしておきます。
1日かつ日曜日ではない
1日が日曜日以外の場合はそれより前の曜日を空欄にしなくてはいけないのでその処理です。
0(日曜日)から1日の曜日まで空白のtdを出力します。
日
日の数字を出力します。
今日の場合はstorngでくくって強調してます。
それ以外は普通に数字を出力しています。
必要あれば処理を足してください。
最終日かつ土曜日ではない
最終日は初日とは逆で、最終日の曜日が土曜日以外の場合、それより後の曜日を空欄にしなくてはいけません。
最終日の曜日から6(土曜日)まで空白のtdを出力します。
最終日、もしくは土曜日
今度はtrの閉じタグです。
trの時とは反対で、土曜日が来ればtrの閉じタグを出力し行を終わらせます。
また最終日は何曜日でも出力します。
曜日を進める
現在の曜日が土曜日の場合は変数に0をいれて日曜日に戻します。
それ以外の場合は1を足して曜日一つ進めます。
表示するカレンダーが複数かつ週の数が6未満の場合
複数月を表示する場合、週の数が違うとテーブルの高さが変わるためその調整です。
最終的な週の数が6ではない場合、全て空のtdの行を出力します。
ほとんどの月は5行か6行なのですが、2月が28日の時かつ1日が日曜日だと行が4行になってしまいますのでその対応のため、forでループさせてます。
この処理がない場合
この処理を行った場合
2月で28日の時かつ初日が日曜日
この処理は必要ないってこともあるかと思いますのでその場合はまるまる削除してください。
また、表示するカレンダーが1つの場合は処理を行いません。
必要ないかと思いますので。
以上です。
機能的には単純にカレンダーを描画するだけなので、案件によっては色々と追加・変更する必要があるかと思いますが、その雛形としてお使いいただければ、、、と思います。