PHPで前月、次月への遷移ボタンを実装したカレンダーを作る
以前書いた記事のコメントで質問をいただいたので新たに書きました。対象の月に対応した前月、次月へ遷移するボタンを含むカレンダーです。
関連記事
今回の記事は、だいぶ前(6年前!)に書いた以下の記事の派生です。
最近Webの仕事をめっきりやっていないので今風のコードは書けないのですが…! 過去の記事を活かして「私だったらこうやって書くかな~」という内容ですので、どうぞ参考程度にご覧ください。
完成予想図
ブラウザで見るとこのような形になるものを想定します。CSSは前の記事をご参照ください。
上部に出力している「クリックされた日付」は動作確認用なので運用時は不要です。この日付がカレンダーに含まれていれば、そこが黄色くなります。日付をクリックされずにページが読み込まれた場合(初回読み込み時など)は、この日付は「本日」が適用されます。
「クリックされた日付」は、初回読み込み時に「本日」が適用されたのち、カレンダー内のいずれかの日付をクリックすることで日付情報が上書きされます。また、次にカレンダー内の日付をクリックするまで、ひとつ前の日付情報を保持します。そのため、保持している「クリックされた日付」と、「カレンダー出力する年月」が一致しないということも起こります。
たとえば、「2020/10/24」を保持したまま「<<」ボタンを押して「2010/09」のカレンダーに遷移したとき、黄色の日付は現れません。そのまま「>>」ボタンで「2010/10」のカレンダーに遷移すれば、保持されている「2020/10/24」に黄色が付きます。
このあたり、「月が変わったならその月の1日を対象にしたい」とか「ひとつ前の月の同じ日を対象にしたい」とかあるかもしれませんので、そのあたりはご自由にカスタマイズしてみてください。
出力したいhtml
というわけで、どんな形のhtmlを出力させたいのか考えてみます。
<table class="rsv_calendar"> <form action="" method="post"> <caption> <input type="submit" name="calendar[2020-09*2020-10-24]" value="<<"> 2020年10月 <input type="submit" name="calendar[2020-11*2020-10-24]" value=">>"> </caption> <thead> <tr> <th scope="col" title="日">日</th> <!-- 略(土曜まで続く) --> </tr> </thead> <tbody> <tr> <td colspan="4" class="pad"> </td> <td><input type="submit" name="calendar[2020-10-01]" value="1"></td> <td><input type="submit" name="calendar[2020-10-02]" value="2"></td> <!-- 略 --> </tr> <tr> <!-- 略(最終日まで続く) --> </tr> </tbody> </form> </table>
ハイライトしてあるのが、前月・次月のボタン出力部分です。カレンダーとして出力させたい年月の情報とともに保持している日付情報も組み込みます。
カレンダーを出力する関数
上記のhtmlを出力する関数です。
function get_rsv_calendar($yyyy, $mm, $date) { $thisyear = $yyyy; //年 $thismonth = $mm; //月 $unixmonth = mktime(0, 0 , 0, $thismonth, 1, $thisyear); //該当月1日のタイムスタンプ $last_day = date('t', $unixmonth); //該当月の日数 $prev = date('Y-m', strtotime('-1 month', $unixmonth)); //前月の算出 $next = date('Y-m', strtotime('+1 month', $unixmonth)); //次月の算出 $calendar_output = '<table class="rsv_calendar">'."\n\t".'<form action="" method="post">'."\n\t".'<caption>'; $calendar_output .= "\n\t\t".'<input type="submit" name="calendar[' . $prev . '*' . $date . ']" value="<<">'; $calendar_output .= "\n\t\t". $thisyear .'年' . $thismonth . '月'; $calendar_output .= "\n\t\t".'<input type="submit" name="calendar[' . $next . '*' . $date . ']" value=">>">'; $calendar_output .= "\n\t</caption>\n\t<thead>\n\t<tr>"; $myweek = array("日", "月", "火", "水", "木", "金", "土"); //曜日定義 foreach ( $myweek as $wd ) { $calendar_output .= "\n\t\t<th scope=\"col\" title=\"$wd\">$wd</th>"; //曜日出力 } $calendar_output .= ' </tr> </thead> <tbody> <tr>'; $pad = date('w', $unixmonth); //該当月1日の曜日番号(日:0~土:6) if ( 0 != $pad ) $calendar_output .= "\n\t\t".'<td colspan="'. $pad .'" class="pad"> </td>'."\n\t\t"; for ( $day = 1; $day <= $last_day; ++$day ) { //1日から最終日まで繰り返し if ( isset($newrow) && $newrow ) $calendar_output .= "\n\t</tr>\n\t<tr>\n\t\t"; //行フラグ$newrowがtrueなら $newrow = false; //行フラグリセット $sp_date = explode("-", $date); //引数$dateを分割 if ( $day == $sp_date[2] && $thismonth == $sp_date[1] && $thisyear == $sp_date[0] ) $calendar_output .= '<td id="current">'; //引数と一致する日にid付加 elseif ( $day == date('j') && $thismonth == date('m') && $thisyear == date('Y') ) $calendar_output .= '<td id="today">'; //本日と一致する日にid付加 else $calendar_output .= '<td>'; $calendar_output .= '<input type="submit" name="calendar['.$thisyear.'-'.str_pad($thismonth,2,"0",STR_PAD_LEFT).'-'.str_pad($day,2,"0",STR_PAD_LEFT).']" value="'.$day.'">'; $calendar_output .= "</td>\n\t\t"; if ( 6 == date('w', mktime(0, 0 , 0, $thismonth, $day, $thisyear)) ) $newrow = true; //最終列なら行フラグを立てる } $pad = 7 - date('w', mktime(0, 0 , 0, $thismonth, $day, $thisyear)); if ( $pad != 0 && $pad != 7 ) $calendar_output .= "\n\t\t".'<td class="pad" colspan="'. $pad .'"> </td>'; //余ったtdを埋める $calendar_output .= "\n\t</tr>\n\t</tbody>\n\t</form>\n</table>"; echo $calendar_output; //出力 }
カレンダー出力する「年」と「月」、それと「クリックされた日付」の情報を引数として持ってきているので、それを計算したりくっつけたりして前月、次月のボタンを作成しています。
利用する
クリックされたボタンの情報から、カレンダー出力する「年」「月」、それと「日付情報」を取得して、関数に引き渡して出力させます。
<?php //タイムゾーンセット date_default_timezone_set('Asia/Tokyo'); //日付情報を取得 if ( isset($_POST['calendar']) ){ //クリック値がある場合 $tmp = !is_string(key($_POST['calendar'])) ? '' : key($_POST['calendar']); if ( strpos($tmp,'*') !== false ){ //前後月の遷移ボタンがクリックされた場合 $date = substr($tmp, 8, 10); //保持されている日付 $get_y = substr($tmp, 0, 4); //年 $get_m = substr($tmp, 5, 2); //月 } else { //カレンダー内の日付がクリックされた場合 $date = $tmp; //日付 $get_y = date('Y', strtotime($date)); //年 $get_m = date('n', strtotime($date)); //月 } } else { //クリック値がない場合 $date = date('Y-m-d'); //本日(YYYY-MM-DDの形) $get_y = date('Y'); //本日の年 $get_m = date('n'); //本日の月 } ?> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Title</title> </head> <body> <!-- クリックされた日付を出力(動作確認用) --> <?php echo $date; ?> <!-- カレンダー部分 --> <div id="calendar_box"> <?php get_rsv_calendar($get_y, $get_m, $date); ?> </div> </body> </html>
クリックされた値を持っている場合、「*」が含まれていたら「前月」もしくは「次月」がクリックされたことになるので、対象の「年」「月」「日付情報」を取り出します。「*」が含まれていなければ日付がクリックされたことになるので、その日付から「年」「月」を算出します。
クリックされた値がない(初回読み込み時など)場合は、本日の日付から算出します。
こんな感じで動くのではないかと思います!
コメントは承認制ですので、反映までしばらくお待ち下さい。(稀にスパムの誤判定にて届かないこともあるようですので、必要な際はお問い合わせからお願い致します。)
YouTubeでQ&Aコンテンツを企画しています
運営しているYouTubeチャンネルで、ご相談やご質問を募集しています。動画のコメントやお問い合わせページからお気軽にご相談をお寄せください。