首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 日曆程式完整實作:從基礎日期函式到物件導向元件

     編輯:PHP 相關知識

核心日期函式:date() 與 mktime()

PHP 內建強大的日期處理函式,生成月曆只需兩個關鍵資訊:

  • 當月總天數:date('t', $timestamp)
  • 該月 1 號是星期幾:date('w', $timestamp)(0=週日, 6=週六)

mktime(0,0,0,$month,1,$year) 可產生該月第一天的 Unix 時間戳。

程序式實作(單一檔案版)

<?php
$month = isset($_GET['m']) ? (int)$_GET['m'] : (int)date('n');
$year  = isset($_GET['y']) ? (int)$_GET['y'] : (int)date('Y');

// 邊界檢查
$month = max(1, min(12, $month));
$year  = max(1970, min(2038, $year));

$firstDayTs = mktime(0, 0, 0, $month, 1, $year);
$startWeek  = (int)date('w', $firstDayTs); // 0-6
$dayNum     = (int)date('t', $firstDayTs); // 28-31

// 上/下月連結
$prevMonth = $month === 1 ? 12 : $month - 1;
$prevYear  = $month === 1 ? $year - 1 : $year;
$nextMonth = $month === 12 ? 1 : $month + 1;
$nextYear  = $month === 12 ? $year + 1 : $year;
?>
<table class="calendar">
  <caption>
    <a href="?m=<?= $prevMonth ?>&y=<?= $prevYear ?>">«</a>
    <?= $year ?> 年 <?= $month ?> 月
    <a href="?m=<?= $nextMonth ?>&y=<?= $nextYear ?>">»</a>
  </caption>
  <thead>
    <tr><th>日</th><th>一</th><th>二</th><th>三</th><th>四</th><th>五</th><th>六</th></tr>
  </thead>
  <tbody>
    <tr>
    <?php
    // 前導空白格
    for ($i = 0; $i < $startWeek; $i++) echo '<td>&nbsp;</td>';
    
    for ($day = 1; $day <= $dayNum; $day++) {
        $isToday = ($day === (int)date('j') && $month === (int)date('n') && $year === (int)date('Y'));
        $class = $isToday ? ' class="today"' : '';
        echo "<td$class>$day</td>";
        
        // 週六換行
        if (($startWeek + $day) % 7 === 0) {
            if ($day !== $dayNum) echo '</tr><tr>';
        }
    }
    // 尾部填滿
    $endWeek = ($startWeek + $dayNum) % 7;
    if ($endWeek !== 0) {
        for ($i = $endWeek; $i < 7; $i++) echo '<td>&nbsp;</td>';
    }
    ?>
    </tr>
  </tbody>
</table>

物件導向版:Calendar 類別(可複用、可擴充)

<?php
class Calendar {
    private int $year;
    private int $month;
    private array $weeks = ['日','一','二','三','四','五','六'];
    private string $baseUrl;

    public function __construct(int $year = 0, int $month = 0, string $baseUrl = '') {
        $this->year    = $year ?: (int)date('Y');
        $this->month   = $month ?: (int)date('n');
        $this->baseUrl = $baseUrl ?: basename($_SERVER['PHP_SELF']);
        $this->clamp();
    }

    private function clamp(): void {
        $this->month = max(1, min(12, $this->month));
        $this->year  = max(1970, min(2038, $this->year));
    }

    public function render(): string {
        $firstDayTs = mktime(0,0,0, $this->month, 1, $this->year);
        $startWeek  = (int)date('w', $firstDayTs);
        $dayNum     = (int)date('t', $firstDayTs);
        $todayStr   = date('Y-n-j');

        $html = '<table class="calendar">';
        $html .= $this->renderHeader();
        $html .= '<thead><tr>';
        foreach ($this->weeks as $w) $html .= "<th>$w</th>";
        $html .= '</tr></thead><tbody><tr>';

        // 前導空格
        for ($i = 0; $i < $startWeek; $i++) $html .= '<td>&nbsp;</td>';

        for ($day = 1; $day <= $dayNum; $day++) {
            $dateStr = "$this->year-$this->month-$day";
            $class = ($dateStr === $todayStr) ? ' class="today"' : '';
            $html .= "<td$class>$day</td>";

            if (($startWeek + $day) % 7 === 0 && $day !== $dayNum) {
                $html .= '</tr><tr>';
            }
        }

        // 尾部填滿
        $endWeek = ($startWeek + $dayNum) % 7;
        if ($endWeek !== 0) {
            for ($i = $endWeek; $i < 7; $i++) $html .= '<td>&nbsp;</td>';
        }
        $html .= '</tr></tbody></table>';
        return $html;
    }

    private function renderHeader(): string {
        $pm = $this->month === 1 ? 12 : $this->month - 1;
        $py = $this->month === 1 ? $this->year - 1 : $this->year;
        $nm = $this->month === 12 ? 1 : $this->month + 1;
        $ny = $this->month === 12 ? $this->year + 1 : $this->year;

        $url = fn($m,$y) => "$this->baseUrl?m=$m&y=$y";
        return "<caption>"
            . "<a href='{$url($pm,$py)}'>«</a> "
            . "<strong>{$this->year} 年 {$this->month} 月</strong> "
            . "<a href='{$url($nm,$ny)}'>»</a>"
            . "</caption>";
    }
}

// 使用方式
$cal = new Calendar(
    isset($_GET['y']) ? (int)$_GET['y'] : 0,
    isset($_GET['m']) ? (int)$_GET['m'] : 0
);
echo $cal->render();
?>

CSS 樣式建議(RWD 友善)

<style>
.calendar { width: 100%; max-width: 400px; margin: 1rem auto; border-collapse: collapse; font-family: system-ui, sans-serif; }
.calendar caption { padding: .5rem; font-size: 1.1rem; text-align: center; background: #f0f0f0; border: 1px solid #ddd; border-bottom: none; }
.calendar th, .calendar td { width: 14.28%; height: 2.5rem; text-align: center; border: 1px solid #ddd; font-size: .9rem; }
.calendar th { background: #333; color: #fff; font-weight: 600; }
.calendar td.today { background: #333; color: #fff; font-weight: bold; border-color: #333; }
.calendar a { text-decoration: none; color: #0066cc; }
@media (max-width: 480px) {
    .calendar th, .calendar td { height: 2rem; font-size: .8rem; }
}
</style>

進階擴充方向

  • 事件標記:在 render() 中結合資料庫查詢,為特定日期加上事件點點或彈窗連結。
  • 農曆轉換:引入 ChineseCalendar 庫(如 overtrue/laravel-chinese-calendar)顯示農曆節氣。
  • AJAX 切換月份:前端用 fetch() 請求片段,無刷新翻頁。
  • 多語系:將星期陣列、月份名稱抽離為語系檔。

總結

PHP 內建日期函式足以構建功能完整的月曆。程序式寫法適合快速原型,物件導向封裝則利於維護與擴充。搭配語意化 HTML 與彈性 CSS,即可得到無障礙、響應式的日曆元件,作為排程系統、行事曆、報表篩選器的基礎 UI。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved