You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用PHP实现月度DTR(每日考勤记录)?数据库考勤记录匹配问题

实现PHP月度DTR(每日考勤记录)功能及日期匹配方案

嘿,我来帮你搞定PHP实现月度DTR的事儿,尤其是你提到的「跳过缺勤日期只展示有记录日期」这个需求——我之前做考勤系统的时候经常碰到类似的场景,给你梳理个清晰的方案:

第一步:先搞定数据库结构

首先得有个靠谱的考勤记录表,我通常会这么设计(用MySQL举例):

CREATE TABLE attendance (
    id INT AUTO_INCREMENT PRIMARY KEY,
    employee_id INT NOT NULL, -- 关联员工表的ID
    attendance_date DATE NOT NULL, -- 考勤日期,用DATE类型避免格式问题
    check_in TIME NULL, -- 上班打卡时间,缺勤的话可以设为NULL
    check_out TIME NULL, -- 下班打卡时间
    status ENUM('present', 'absent', 'late', 'leave') NOT NULL DEFAULT 'absent', -- 考勤状态
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

小提示: 把attendance_date设为DATE类型,后续匹配日期会少很多格式兼容的麻烦。

第二步:从数据库提取指定员工的月度考勤记录

接下来用PHP查询目标员工当月的所有考勤记录,并且把结果整理成「日期为键」的数组,方便后续快速匹配:

// 假设你已经用PDO或mysqli连接了数据库,这里用PDO示例
$pdo = new PDO('mysql:host=localhost;dbname=your_db', 'username', 'password');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

// 要查询的员工ID和月份(可以改成用户输入的参数)
$employeeId = 123;
$targetYear = date('Y');
$targetMonth = date('m');

// 查询该员工当月的所有考勤记录,按日期排序
$stmt = $pdo->prepare("
    SELECT attendance_date, check_in, check_out, status 
    FROM attendance 
    WHERE employee_id = ? 
      AND YEAR(attendance_date) = ? 
      AND MONTH(attendance_date) = ? 
    ORDER BY attendance_date ASC
");
$stmt->execute([$employeeId, $targetYear, $targetMonth]);
$attendanceData = $stmt->fetchAll(PDO::FETCH_ASSOC);

// 整理成以日期为键的数组,方便后续快速查找
$attendanceRecords = [];
foreach ($attendanceData as $record) {
    $attendanceRecords[$record['attendance_date']] = $record;
}

第三步:生成DTR表单并跳过缺勤日期

这里分两种常见场景,你可以按需选择:

场景1:只展示有考勤记录的日期(直接跳过缺勤日)

这种最简单,直接遍历查询到的记录就行,自然就跳过了没有记录的缺勤日期:

echo '<div class="dtr-container">';
echo '<h2>月度考勤记录(员工ID:' . $employeeId . ' | ' . $targetYear . '年' . $targetMonth . '月)</h2>';
echo '<table border="1" cellpadding="8">';
echo '<tr><th>日期</th><th>上班时间</th><th>下班时间</th><th>状态</th></tr>';

foreach ($attendanceData as $record) {
    echo '<tr>';
    echo '<td>' . $record['attendance_date'] . '</td>';
    echo '<td>' . ($record['check_in'] ?? '无') . '</td>';
    echo '<td>' . ($record['check_out'] ?? '无') . '</td>';
    echo '<td>' . ucfirst($record['status']) . '</td>';
    echo '</tr>';
}

echo '</table></div>';

场景2:遍历当月所有日期,遇到缺勤日直接跳过不显示

如果需要严格按月度日期顺序,但只展示有记录的行,就先生成当月所有日期,再逐一匹配:

// 生成当月所有日期的数组
$firstDayOfMonth = "$targetYear-$targetMonth-01";
$lastDayOfMonth = date('Y-m-t', strtotime($firstDayOfMonth));
$currentDate = $firstDayOfMonth;
$monthDates = [];

while ($currentDate <= $lastDayOfMonth) {
    $monthDates[] = $currentDate;
    $currentDate = date('Y-m-d', strtotime($currentDate . ' +1 day'));
}

// 生成DTR表格
echo '<div class="dtr-container">';
echo '<h2>月度考勤记录(员工ID:' . $employeeId . ' | ' . $targetYear . '年' . $targetMonth . '月)</h2>';
echo '<table border="1" cellpadding="8">';
echo '<tr><th>日期</th><th>上班时间</th><th>下班时间</th><th>状态</th></tr>';

foreach ($monthDates as $date) {
    // 只有当该日期有考勤记录时才输出行
    if (isset($attendanceRecords[$date])) {
        $record = $attendanceRecords[$date];
        echo '<tr>';
        echo '<td>' . $date . '</td>';
        echo '<td>' . ($record['check_in'] ?? '无') . '</td>';
        echo '<td>' . ($record['check_out'] ?? '无') . '</td>';
        echo '<td>' . ucfirst($record['status']) . '</td>';
        echo '</tr>';
    }
    // 没有记录就跳过,不输出任何内容
}

echo '</table></div>';

一些额外的优化建议

  • 可以添加员工选择器和月份选择器,让用户能切换不同员工和月份生成DTR;
  • 如果需要区分「未打卡」和「请假」,可以在status字段里细化枚举值;
  • 可以给DTR表格加上样式,让它更美观,比如用CSS隐藏边框、添加 hover 效果。

内容的提问来源于stack exchange,提问作者Decent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:40:31