PHP 万年历类完整代码与实现逻辑解析
使用 PHP 开发万年历的核心在于准确计算每个月的天数以及该月1号对应的星期几。本文将通过分析 `mktime` 函数的应用,演示如何构建一个 `Calendar` 类,自动处理闰年判断、月份边界校验,并以 HTML 表格形式清晰展示日历布局,支持上下月份切换。
核心逻辑与准备
实现万年历主要依赖两个关键数据点:
- 当月总天数 ($days):决定循环输出天数的结束条件。PHP 中可通过
date("t", ...)快速获得,无需手动处理大月小月或闰年问题。 - 当月1号的星期几 ($dayofweek):决定在输出具体日期前需要预留多少个空白占位符。这确保了日期能从正确的星期列开始排列。
最终呈现效果应为一个清晰的网格表格,顶部显示标题,中间为星期与日期对应关系,底部附带跳转链接。
实现步骤
第1步:定义 Calendar 类并初始化参数
目的是接收用户指定的年份和月份,若未提供则默认为当前时间,并进行合法性校验。
复制代码 代码如下:
<?php
/**
* PHP万年历
*/
class Calendar {
protected $_table; // 存储生成的HTML表格内容
protected $_currentDate;// 显示用的日期字符串,如"2023年10月"
protected $_year; // 目标年份
protected $_month; // 目标月份
protected $_days; // 目标月份的天数
protected $_dayofweek; // 目标月份1号是星期几(0-6)
public function __construct() {
$this->_table = "";
// 获取GET参数中的y和m,若无则取当前时间
$this->_year = isset($_GET["y"]) ? intval($_GET["y"]) : date("Y");
$this->_month = isset($_GET["m"]) ? intval($_GET["m"]) : date("m");
// 处理月份越界情况:大于12则进位到下年1月,小于1则退位到上年12月
if ($this->_month > 12) {
$this->_month = 1;
$this->_year++;
}
if ($this->_month < 1) {
$this->_month = 12;
$this->_year--;
}
// 构造显示用的日期标题
$this->_currentDate = $this->_year . '年' . $this->_month . '月份';
// 核心计算:
// mktime(时,分,秒,月,日,年) 构造时间戳
// date("t", ...) 获取该月最后一天是几号(即总天数)
$this->_days = date("t", mktime(0, 0, 0, $this->_month, 1, $this->_year));
// date("w", ...) 获取该月1号是星期几 (0=周日, 1=周一...)
$this->_dayofweek = date("w", mktime(0, 0, 0, $this->_month, 1, $this->_year));
}
}
第2步:渲染表头信息
此方法负责生成 HTML 表格的头部,包括月份标题行和星期标题行。我们将星期日设置为红色以作区分。
/**
* 输出标题和表头信息
*/
protected function _showTitle() {
// 创建表格并开始表头
$this->_table = "<table border='1' cellpadding='5' cellspacing='0'>";
$this->_table .= "<thead><tr align='center' style='background:#f0f0f0;'>";
$this->_table .= "<th colspan='7'>" . $this->_currentDate . "</th>";
$this->_table .= "</tr></thead>";
// 星期行
$this->_table .= "<tbody><tr>";
$this->_table .= "<td style='color:red'>星期日</td>";
$this->_table .= "<td>星期一</td>";
$this->_table .= "<td>星期二</td>";
$this->_table .= "<td>星期三</td>";
$this->_table .= "<td>星期四</td>";
$this->_table .= "<td>星期五</td>";
$this->_table .= "<td style='color:red'>星期六</td>";
$this->_table .= "</tr>";
}
第3步:循环生成日期单元格
这是核心逻辑部分。首先根据 $dayofweek 输出开头的空白占位符,然后循环输出 1 到 $days 的天数。当计数达到 7 的倍数时,强制换行。
/**
* 输出日期信息
*/
protected function _showDate() {
$nums = $this->_dayofweek + 1;
// 输出1号之前的空白格子,确保1号对齐正确的星期列
for ($i = 1; $i <= $this->_dayofweek; $i++) {
$this->_table .= "<td> </td>";
}
// 输出实际天数
for ($i = 1; $i <= $this->_days; $i++) {
// 每7个数字换一行
if ($nums % 7 == 0) {
$this->_table .= "<td>$i</td></tr><tr>";
} else {
$this->_table .= "<td>$i</td>";
}
$nums++;
}
// 闭合标签
$this->_table .= "</tbody></table>";
}
第4步:添加月份切换导航
在表格下方添加“上一月”和“下一月”的超链接,通过 GET 参数传递新的年份和月份,重新触发类实例化。
/**
* 添加导航链接
*/
protected function _addNav() {
// 注意:简单的月份加减可能导致跨年错误,生产环境建议更严谨的逻辑
// 此处沿用原稿简单逻辑,仅做展示
$prevMonth = ($this->_month - 1);
$prevYear = $this->_year;
if($prevMonth < 1) { $prevMonth = 12; $prevYear--; }
$nextMonth = ($this->_month + 1);
$nextYear = $this->_year;
if($nextMonth > 12) { $nextMonth = 1; $nextYear++; }
$navHtml = "<h3>";
$navHtml .= "<a href='?y={$prevYear}&m={$prevMonth}'>上一月</a> ";
$navHtml .= "<a href='?y={$nextYear}&m={$nextMonth}'>下一月</a>";
$navHtml .= "</h3>";
echo $navHtml;
}
第5步:组合输出
将上述步骤组合,并在页面末尾执行实例化。
/**
* 调用入口
*/
public function showCalendar() {
$this->_showTitle();
$this->_showDate();
echo $this->_table;
$this->_addNav();
}
}
// 执行
$calc = new Calendar();
$calc->showCalendar();
?
完成判断与总结
当代码运行后,浏览器应展示出包含正确日期分布的表格,且点击上下月链接能无刷新或跳转式地更新日历内容。以上关于 PHP 万年历类的详细内容,更多关于 PHP 日期处理与 Web 开发的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













