CakePHPでカレンダーヘルパーを作ってみた
http://cakephp.jp/modules/newbb/viewtopic.php?topic_id=1786&forum=9&post_id=4263からお越しの方、祝日判定付きではありませんので、ご注意ください。
CakePHPのhelperをテスト的に作ることにしました。とりあえず現実的に利用機会がありそうなCalandarHelperにしました。
本当は祝日判定とかやるべきなんでしょうけど、春分の日、秋分の日の確定が面倒な上に、祝日情報はメンテナンスを考えるとデータベースで保持する方がよさそうなので、特にやっていません。(気が向いたらやるかもしれません)
ってことで単純にカレンダーを表示するだけになっちゃいました。(CSSも別途記述する必要があります)
CalendarHelperは、app/views/helpers/calendar.phpに作成します。
<?php /** * カレンダーヘルパー. * */ class CalendarHelper extends AppHelper { var $_defaultLang = 'en'; var $_week = array( 'en' => array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'), 'ja' => array('日', '月', '火', '水', '木', '金', '土') ); /** * カレンダーを生成する. * * @param string $lang 言語 * @param integer $date 日付 * @return カレンダー */ function makeCalendar($lang = null, $date = null) { if (is_null($date)) { $date = date('Ymd'); } if (is_null($lang)) { $lang = $this->_defaultLang; } $year = substr($date, 0, 4); $month = substr($date, 4, 2); $day = substr($date, 6, 2); if (!checkdate($month, $day, $year)) { $this->log('Invalid date format!'); } return $this->output( "<div id=\"calendar\"><div id=\"calendar-header\">".$year."年".$month."月</div><table id=\"calendar-content\">". $this->_makeWeekHeader($lang).$this->_makeCalendarContent($year, $month, $date)."</table></div>" ); } /** * 週ヘッダーを生成する. * * @param string $lang 言語 * @return 週ヘッダー */ function _makeWeekHeader($lang = null) { if (is_null($lang)) { $lang = $this->_defaultLang; } $cell = array(); foreach ($this->_week[$lang] as $weekId => $week) { array_push($cell, "<td class=\"week_".strtolower($this->_week[$this->_defaultLang][$weekId])."\">".$week."</td>"); } return "<tr id=\"week_header\">".implode("", $cell)."</tr>"; } /** * カレンダーコンテンツを生成する. * * @param integer $year 年 * @param integer $month 月 * @param integer $selecteday 選択日 * @return カレンダーコンテンツ */ function _makeCalendarContent($year, $month, $selectedDay) { if (!is_numeric($year) || !is_numeric($month) || !is_numeric($selectedDay)) { throw new Exception("Invalid parameters!"); } $calendar = array(); $weekNo = 1; // 月内での週番号(第○週) $last = substr($this->_getLastDay($year, $month), 6, 2); for ($day = 1; $day <= $last; $day++) { $date = $year.$month.sprintf("%02d", $day); // Ymd形式 $weekId = $this->_getWeekIdOfDay($year, $month, $day, $this->_defaultLang); $attr = array(); if ($this->_getToday() == $date) { array_push($attr, 'today'); } if ($selectedDay == $date) { array_push($attr, 'selected'); } // TODO 祝日判定 if (false) { array_push($attr, 'holiday'); } $calendar[$weekNo][$weekId] = array('day' => $day, 'attribute' => $attr); // 翌週へ if ($weekId == count($this->_week[$this->_defaultLang]) - 1) { $weekNo++; } } // debug($calendar); $default = array('day' => '', 'attribute' => array()); $c = array(); for ($rowIdx = 1; $rowIdx <= count($calendar); $rowIdx++) { $elements = array(); for ($colIdx = 0; $colIdx < count($this->_week[$this->_defaultLang]); $colIdx++) { $day = $default; if (array_key_exists($colIdx, $calendar[$rowIdx])) { $day = $calendar[$rowIdx][$colIdx]; } // debug($day); array_push( $elements, "<td class=\"week_".strtolower($this->_week[$this->_defaultLang][$colIdx])." ".implode(" ", $day['attribute'])."\">".$day['day']."</td>" ); } array_push($c, "<tr class=\"week\">".implode("", $elements)."</tr>"); } return implode("", $c); } /** * 月初の日付を返す. * * @param integer $year 年 * @param integer $month 月 * @param unknown_type $format フォーマット * @return 月初の日付 */ function _getFirstDay($year, $month, $format = 'Ymd') { return date($format, mktime(0, 0, 0, $month, 1, $year)); } /** * 月末の日付を返す. * * @param integer $year 年 * @param integer $month 月 * @param string $format フォーマット * @return 月末の日付 */ function _getLastDay($year, $month, $format = 'Ymd') { return date($format, mktime(0, 0, 0, $month + 1, 0, $year)); } /** * 日付を返す. * * @param integer $year 年 * @param integer $month 月 * @param integer $day 日 * @param string $format フォーマット * @return 月末の日付 */ function _getDay($year, $month, $day, $format = 'Ymd') { return date($format, mktime(0, 0, 0, $month, $day, $year)); } /** * 今日の日付を返す. * * @param string $format フォーマット * @return 今日の日付 */ function _getToday($format = 'Ymd') { return date($format); } /** * 曜日IDを返す. * * @param integer $year 年 * @param integer $month 月 * @param integer $day 日 * @param string $lang 言語 * @return 曜日ID */ function _getWeekIdOfDay($year, $month, $day, $lang = null) { if (is_null($lang)) { $lang = $this->_defaultLang; } return $this->_getDay($year, $month, $day, 'w'); } /** * 曜日を返す. * * @param integer $year 年 * @param integer $month 月 * @param integer $day 日 * @param string $lang 言語 * @return 曜日 */ function _getWeekOfDay($year, $month, $day, $lang = null) { if (is_null($lang)) { $lang = $this->_defaultLang; } return $this->_week[$lang][$this->_getDay($year, $month, $day, 'w')]; } } ?>
view側では、以下のように記述します。
- 日付を指定する場合
<?php echo $calendar->makeCalendar('ja', '20090101'); ?>
- 今日の日付の場合
<?php echo $calendar->makeCalendar('ja'); ?>
日付の指定をしなかった場合の出力は以下のようになります。(1行が長くなってしまうので適宜改行を入れています)
<div id="calendar"> <div id="calendar-header">2009年2月</div> <table id="calendar-content"> <tr id="week_header"> <td class="week_sun">日</td> <td class="week_mon">月</td> <td class="week_tue">火</td> <td class="week_wed">水</td> <td class="week_thu">木</td> <td class="week_fri">金</td> <td class="week_sat">土</td> </tr> <tr class="week"> <td class="week_sun ">1</td> <td class="week_mon ">2</td> <td class="week_tue ">3</td> <td class="week_wed ">4</td> <td class="week_thu ">5</td> <td class="week_fri ">6</td> <td class="week_sat ">7</td> </tr> <tr class="week"> <td class="week_sun ">1</td> <td class="week_mon ">2</td> <td class="week_tue ">3</td> <td class="week_wed ">4</td> <td class="week_thu ">5</td> <td class="week_fri ">6</td> <td class="week_sat ">7</td> </tr> <tr class="week"> <td class="week_sun ">8</td> <td class="week_mon ">9</td> <td class="week_tue ">10</td> <td class="week_wed ">11</td> <td class="week_thu ">12</td> <td class="week_fri ">13</td> <td class="week_sat ">14</td> </tr> <tr class="week"> <td class="week_sun ">15</td> <td class="week_mon ">16</td> <td class="week_tue ">17</td> <td class="week_wed ">18</td> <td class="week_thu ">19</td> <td class="week_fri ">20</td> <td class="week_sat ">21</td> </tr> <tr class="week"> <td class="week_sun ">22</td> <td class="week_mon ">23</td> <td class="week_tue ">24</td> <td class="week_wed ">25</td> <td class="week_thu ">26</td> <td class="week_fri today selected">27</td> <td class="week_sat ">28</td> </tr> </table> </div>