phpとjavascriptで営業カレンダーを作る
完成した表示
仕様
・休みは赤色にする
・定休日:祝日と日曜、木曜
・アイコンクリックで表示月変更
設計
・PHPでカレンダーを構築する配列をJSONで出力
・ajaxで受け取り出力する。
1.祝日配列のつくる
内閣府のページに祝日のcsvがあるので、そこからダウンロードする。
https://www8.cao.go.jp/chosei/shukujitsu/gaiyou.html
※csvはUTF-8に変換して保存。
calendar.php
function get_public_holidays(){
$path = "./syukujitsu.csv";
$csv = new SplFileObject($path);
$csv->setFlags(SplFileObject::READ_CSV);
$holidays = [];
foreach ($csv as $key => $line){
$holidays[$line[0]] = $line[1];
}
return $holidays;
}
2.カレンダーを構築する配列をつくる
calendar.php
function make_date_list($year,$month){
$regular_holiday = [0,4]; //定休日:曜日
$public_holidays = get_public_holidays(); //祝日
$target = new \DateTime("{$year}-{$month}-01");
$date = [];
for($i = 0; $i < intval($target->format('t')); $i++){
if($i > 0) $target->modify('+1day');
//祝日
if(isset($public_holidays[$target->format('Y/n/d')])){
$holiday = true;
//定休日
}else if(in_array($target->format('w'),$regular_holiday)){
$holiday = true;
}else{
$holiday = false;
}
$dates[$i] = [
'day' => $target->format('d'),
'week' => $target->format('w'),
'holiday' => $holiday,
];
}
/*カレンダーの空欄箇所*/
$first_date = current($dates);
$end_date = end($dates);
$damy_num = intval($first_date['week']);
if($damy_num > 0){
$damy = [];
for($i = $damy_num - 1;0 <= $i;$i--){
array_unshift($dates,['week'=>$i,'day'=>' ']);
}
}
$damy_num = intval($end_date['week']);
if($damy_num < 6){
$damy = [];
for($i = $damy_num; $i < 6;$i++){
array_push($dates,['week'=>$i,'day'=>' ']);
}
}
return $dates;
}
3.リクエストがよる出力
calendar.php
if(isset($_GET['y']) and $_GET['y']){
$year = $_GET['y'];
}else{
$year = date('Y');
}
if(isset($_GET['m']) and $_GET['m']){
$month = $_GET['m'];
}else{
$month = date('m');
}
$dates = make_date_list($year,$month);
echo json_encode($dates);
4.javascriptでのカレンダー構築
2ヶ月先までの表示にしています。
calendar.js
var nowDate;
var year;
var month;
$(function(){
nowDate = new Date();
year = nowDate.getFullYear(); // 年
month = nowDate.getMonth() + 1; // 月
MakeCalendar();
});
function prev(){
if(month === 1){
month = 12;
year--;
}else{
month--;
}
MakeCalendar();
}
function next(){
if(month === 12){
month = 1;
year++;
}else{
month++;
}
MakeCalendar();
}
function MakeCalendar(){
$.ajax({
url: 'calender.php?y='+year+'&m='+month,
dataType: 'json',
timeout: 10000,
success: function(json) {
var c = '<div class="cal"><div class="cal_header">';
if(nowDate.getFullYear() <= year && (nowDate.getMonth() + 1) < month ){
c += '<a href="" onClick="prev();return false;" class="cal_prev"><img src="./images/cal_prev.png" alt="前の月" width="19"></a>';
}else{}
if(nowDate.getFullYear() >= year && (nowDate.getMonth() + 3) > month ){
c += '<a href="" onClick="next();return false;" class="cal_next"><img src="./images/cal_next.png" alt="次の月" width="19"></a>'
}else{}
c += '<strong>'+year+'年'+month+'月</strong>';
c += '</div>';
c += '<div class="cal_body">';
c += '<table class="table_cal">';
c += '<thead><tr><th>日</th><th>月</th><th>火</th><th>水</th><th>木</th><th>金</th><th>土</th></tr></thead>';
jQuery.each(json, function(i, date) {
if(date.week === '0'){
c += '<tr>';
}else{}
if(date.holiday === true){
c += '<td><span class="closed">'+date.day+'</span></td>';
}else{
c += '<td>'+date.day+'</td>';
}
if(date.week === '6'){
c += '</tr>';
}else{}
});
c += '</tbody></table></div></div>';
$('#calendar').html(c);
},
error: function(xhr, textStatus, error) {
alert('ERR');
}
});
}
4.表示
表示する箇所にタグとCSSを構築して完成。
sample.html
<div id="calendar"></div>
sample.css
.cal{background:#fff;box-shadow:2px 2px 4px rgba(0,0,0,0.2);}
.cal_header{padding:15px 13px;border-bottom:1px solid #ddd;}
.cal_header a,.cal_header span{display:block;}
.cal_header strong{display:block;text-align:center;font-size:1.3rem;color:#005ca2;line-height:19px;}
.cal_prev{float:left;cursor:pointer;}
.cal_next{float:right;cursor:pointer;}
.cal_body{padding:10px 15px;text-align:center;}
.table_cal{width:100%;border-collapse:collapse;}
.table_cal th,.table_cal td{font-size:1.1rem;text-align:center;height:30px;min-width:31px;}
.today{font-weight:bold;text-decoration:underline;}
.closed{display:inline-block;width:22px;height:22px;background:#eb6e8f;color:#fff;border-radius:50%;line-height:23px;}
.cal_bottom{font-size:1.1rem;margin:10px 0 15px;}
.cal_bottom span{vertical-align:middle;margin-right:4px;}