あかまこ
トップへ

PHPでつくる無限カレンダー

まず実行結果。

2019年6月
1
2345678
9101112131415
16171819202122
23242526272829
30


ソースコードは以下。

<?php

/**
 * 手作りカレンダークラス
 */
class calendar{

    
// 本日の情報
    
public $today = array();

    
// 表示するカレンダーの情報
    
public $disp = array();

    
// 日曜始まりデフォルト
    
public $startWeek 0;

    
/**
     * インスタンス化されたときに実行される
     */
    
public function __constract(){
    }

    
/**
     * メンバ変数を初期化する
     */
    
public function init(){
        
self::setStartWeek();
        
self::setToday();
        
self::setDisp();
    }

    
/**
     * HTMLに出力する処理
     */
    
public function echoAll(){
        
$echos = array();
        
$echos[] = self::getTable();
        
$echos[] = self::getTitleTr();
        
$echos[] = self::getBeforeTrTd();
        for(
$day=1;$day<32;$day++){
            
$d str_pad($day2'0'STR_PAD_LEFT);
            if(
checkdate($this->disp['m'], $d$this->disp['Y']) === false){
                break;
            }
            
$ts strtotime($this->disp['Y'].$this->disp['m'].$d);

            
$week self::getWeek($ts);
            
$echos[] = self::getTr($week);
            
$echos[] = self::getTd($week);
            
$echos[] = $day;
            
$echos[] = self::getTdClose();
            
$echos[] = self::getTrClose($week);
        }
        
$echos[] = self::getAfterTrTd($ts);
        
$echos[] = self::getTableClose();
        return 
implode('',$echos);
    }

    public function 
setStartWeek(){
        if (isset(
$_REQUEST['sw']) && in_array($_REQUEST['sw'],array('1','0'))) {
            
// 0 : 日曜始まり, 1 : 月曜始まり
            
$this->startWeek = (int) $_REQUEST['sw'];
        }
    }

    
/**
     * HTMLに出力する年、月を決定している
     */
    
public function setDisp(){
        if (isset(
$_REQUEST['ym']) && strlen($_REQUEST['ym']) === && is_numeric($_REQUEST['ym'])) {
            
$this->disp['Y'] = substr($_REQUEST['ym'], 0,4);
            
$this->disp['m'] = substr($_REQUEST['ym'], 4,2);
            
$this->disp['n'] = $this->disp['m']+0;
        } else if (isset(
$this->today['Y'],$this->today['m'])) {
            
$this->disp['Y'] = $this->today['Y'];
            
$this->disp['m'] = $this->today['m'];
            
$this->disp['n'] = $this->disp['m']+0;
        } else {
            
$this->disp['Y'] = date('Y');
            
$this->disp['m'] = date('m');
            
$this->disp['n'] = date('n');
        }
        
$this->disp['ts'] = strtotime($this->disp['Y'].$this->disp['m'].$this->today['d']);
    }
    public function 
setToday(){
        
$this->today['Y'] = date('Y');
        
$this->today['m'] = date('m');
        
$this->today['d'] = date('d');
        
$this->today['n'] = date('n');
        
$this->today['j'] = date('j');
        
$this->today['ts'] = strtotime($this->today['Y'].$this->today['m'].$this->today['d']);
    }
    function 
getWeek($ts){
        
// 0 (日曜)から 6 (土曜)
        
return (int) date('w',$ts);
    }
    function 
getTable(){
        return 
'<table class="table table-sm table-bordered table-calendar">';
    }
    function 
getTableClose(){
        return 
'</table>';
    }
    function 
getTitleTr(){
        
$weeks = array('月''火''水''木''金''土''日');
        if (
$this->startWeek === 0) {
            
$weeks = array('日''月''火''水''木''金''土');
        }
        
$return '<tr class="calendar-title">';
        foreach (
$weeks as $i => $week){
            
$return .= self::getTd(($i+$this->startWeek === $i+$this->startWeek));
            
$return .= $week;
            
$return .= self::getTdClose();
        }
        
$return .= '</tr>';
        return 
$return;
    }
    function 
getBeforeTrTd(){
        
$firstWeek self::getWeek(strtotime($this->disp['Y'].$this->disp['m'].'01'));

        if (
$firstWeek === $this->startWeek) {
            
// 1日が左端からピッタリ埋まっていれば何もしない
            
return '';
        }

        if (
$this->startWeek === 0) {
            
// 日曜始まり
            // あと何個 td が必要か
            
$endI $firstWeek;
        } else {
            
// 月曜始まり
            // あと何個 td が必要か
            
$endI $firstWeek 1;
            if (
$firstWeek === 0) {
                
$endI 6;
            }
        }

        
$return '<tr>';

        
// その月の1日がくるまでtdを埋める
        
for($i=0;$i<$endI;$i++){
            
$return .= self::getTd($i+$this->startWeek);
            
$return .= ' ';
            
$return .= self::getTdClose();
        }
        return 
$return;
    }
    function 
getAfterTrTd($lastTs){
        
$lastWeek self::getWeek($lastTs);


        if (
$this->startWeek === 0) {
            
// 日曜始まり
            
if ($lastWeek === 6) {
                
// 末日が右端までピッタリ埋まっていれば何もしない
                
return '';
            }
            
// あと何個 td が必要か
            
$endI $lastWeek;
        } else {
            
// 月曜始まり
            
if ($lastWeek === 0) {
                
// 末日が右端までピッタリ埋まっていれば何もしない
                
return '';
            }
            
// あと何個 td が必要か
            
$endI $lastWeek;
        }

        
$return '';
        
// その月の末日がくるまでtdを埋める
        
for($i=1;$i<=$endI && $i<7;$i++){
            
$return .= self::getTd($i+$lastWeek === $i+$lastWeek);
            
$return .= ' ';
            
$return .= self::getTdClose();
        }
        
$return .= '</tr>';
        return 
$return;
    }
    function 
getTd($week){
        if (
$week === 6) {
            return 
'<td class="sat">';
        }
        if (
$week === 0) {
            return 
'<td class="sun">';
        }
        return 
'<td>';
    }
    function 
getTdClose(){
        return 
'</td>';
    }
    function 
getTr($week){
        if (
$week === $this->startWeek) {
            return 
'<tr>';
        }
        return 
'';
    }
    function 
getTrClose($week){
        if (
$this->startWeek === 0) {
            
// 日曜始まり
            
if ($week === 6) {
                return 
'</tr>';
            }
        } else {
            
// 月曜始まり
            
if ($week === 0) {
                return 
'</tr>';
            }
        }
        return 
'';
    }

    
/**
     * リンクを作成する。
     */
    
function getNextLink(){
        
// 次のページで現在表示されている年月の翌月を表示するためのリンク先のURLパラメータ
        
return 'ym='.date('Ym',strtotime($this->disp['Y'].$this->disp['m'].'01 + 1month'));
    }

    
/**
     * リンクを作成する
     */
    
function getPreLink(){
        
// 次のページで現在表示されている年月の前月を表示するためのリンク先のURLパラメータ
        
return 'ym='.date('Ym',strtotime($this->disp['Y'].$this->disp['m'].'01 - 1month'));
    }
}
$c = new calendar();
$c->init();

?>
<div class="row text-center mb-3">
    <div class="col-4">
        <a href="?sw=<?php echo $c->startWeek;?>&<?php echo $c->getPreLink();?>" class="btn btn-sm btn-outline-primary">前の月</a>
    </div>
    <div class="col-4 year-month">
        <?php echo $c->disp['Y'];?><?php echo $c->disp['n'];?>
    </div>
    <div class="col-4">
        <a href="?sw=<?php echo $c->startWeek;?>&<?php echo $c->getNextLink();?>" class="btn btn-sm btn-outline-primary">次の月</a>
    </div>
</div>
<div><?php echo $c->echoAll();?></div>
<div class="row">
    <div class="col-12 text-right">
        <a href="?sw=<?php echo $c->startWeek === '0' '1';?>&<?php echo $c->getNextLink();?>" class="btn btn-sm btn-outline-secondary"><?php echo $c->startWeek === '日曜始まり表示' '月曜始まり表示切り替え' ?></a>
    </div>
</div>