PHP项目考勤报表如何自动生成统计

wen PHP项目 23

本文目录导读:

PHP项目考勤报表如何自动生成统计

  1. 整体流程设计
  2. 数据库表结构示例
  3. PHP统计逻辑实现
  4. 自动定时生成(cron任务)
  5. 完整调用示例(Web页面)
  6. 优化建议
  7. 关键技术点总结

要为PHP项目实现考勤报表的自动生成和统计,通常需要结合数据库查询PHP脚本处理以及报表导出功能,下面是完整的实现方案,包含核心逻辑和代码示例。


整体流程设计

考勤数据表 → PHP查询统计 → 计算各类指标 → 生成报表(HTML/Excel/PDF)
                                          ↓
                                   自动定时任务(cron)

数据库表结构示例

假设有以下表:

考勤记录表 attendance

CREATE TABLE attendance (
    id INT PRIMARY KEY AUTO_INCREMENT,
    user_id INT NOT NULL,
    date DATE NOT NULL,
    clock_in DATETIME,      -- 上班打卡
    clock_out DATETIME,     -- 下班打卡
    status VARCHAR(20),     -- normal / late / early_leave / absent
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

用户表 users(假设已有)

-- user_id, name, department, work_start_time, work_end_time 等

PHP统计逻辑实现

基础统计类

class AttendanceReportGenerator {
    private $db;
    private $startDate;
    private $endDate;
    public function __construct($pdo, $startDate, $endDate) {
        $this->db = $pdo;
        $this->startDate = $startDate;
        $this->endDate = $endDate;
    }
    /**
     * 获取所有用户的考勤统计
     */
    public function getReport() {
        $sql = "SELECT 
                    u.id,
                    u.name,
                    u.department,
                    COUNT(a.id) as total_days,
                    SUM(CASE WHEN a.status = 'late' THEN 1 ELSE 0 END) as late_days,
                    SUM(CASE WHEN a.status = 'early_leave' THEN 1 ELSE 0 END) as early_leave_days,
                    SUM(CASE WHEN a.status = 'absent' THEN 1 ELSE 0 END) as absent_days,
                    SUM(CASE WHEN a.status = 'normal' THEN 1 ELSE 0 END) as normal_days,
                    SUM(TIMESTAMPDIFF(HOUR, a.clock_in, a.clock_out)) as total_work_hours
                FROM users u
                LEFT JOIN attendance a ON u.id = a.user_id 
                    AND a.date BETWEEN :start AND :end
                GROUP BY u.id
                ORDER BY u.department, u.name";
        $stmt = $this->db->prepare($sql);
        $stmt->execute([
            ':start' => $this->startDate,
            ':end' => $this->endDate
        ]);
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    /**
     * 计算出勤率
     */
    public function calculateAttendanceRate($data) {
        if ($data['total_days'] == 0) return 0;
        return round(($data['normal_days'] / $data['total_days']) * 100, 2);
    }
    /**
     * 计算平均工时
     */
    public function calculateAverageHours($data) {
        if ($data['total_days'] == 0) return 0;
        return round($data['total_work_hours'] / $data['total_days'], 2);
    }
}

生成统计报表(HTML预览 + 导出Excel)

class ReportExporter {
    /**
     * 导出为Excel(使用 PhpSpreadsheet)
     */
    public function exportToExcel($data, $filename = 'attendance_report.xlsx') {
        require_once 'vendor/autoload.php';
        $spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();
        // 表头
        $headers = ['姓名', '部门', '出勤天数', '迟到', '早退', '缺勤', '正常', '总工时', '出勤率(%)', '平均工时'];
        $sheet->fromArray($headers, NULL, 'A1');
        // 数据填充
        $row = 2;
        foreach ($data as $item) {
            $sheet->setCellValue('A' . $row, $item['name']);
            $sheet->setCellValue('B' . $row, $item['department']);
            $sheet->setCellValue('C' . $row, $item['total_days']);
            $sheet->setCellValue('D' . $row, $item['late_days']);
            $sheet->setCellValue('E' . $row, $item['early_leave_days']);
            $sheet->setCellValue('F' . $row, $item['absent_days']);
            $sheet->setCellValue('G' . $row, $item['normal_days']);
            $sheet->setCellValue('H' . $row, $item['total_work_hours']);
            $sheet->setCellValue('I' . $row, $this->calculateAttendanceRate($item));
            $sheet->setCellValue('J' . $row, $this->calculateAverageHours($item));
            $row++;
        }
        // 自动列宽
        foreach (range('A', 'J') as $col) {
            $sheet->getColumnDimension($col)->setAutoSize(true);
        }
        $writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment;filename="' . $filename . '"');
        header('Cache-Control: max-age=0');
        $writer->save('php://output');
        exit;
    }
    /**
     * 生成HTML表格预览
     */
    public function generateHtmlTable($data) {
        $html = '<table class="table table-bordered">';
        $html .= '<thead><tr>
                    <th>姓名</th>
                    <th>部门</th>
                    <th>出勤天数</th>
                    <th>迟到</th>
                    <th>早退</th>
                    <th>缺勤</th>
                    <th>正常</th>
                    <th>总工时</th>
                    <th>出勤率</th>
                    <th>平均工时</th>
                </tr></thead><tbody>';
        foreach ($data as $item) {
            $html .= '<tr>';
            $html .= '<td>' . htmlspecialchars($item['name']) . '</td>';
            $html .= '<td>' . htmlspecialchars($item['department']) . '</td>';
            $html .= '<td>' . $item['total_days'] . '</td>';
            $html .= '<td>' . $item['late_days'] . '</td>';
            $html .= '<td>' . $item['early_leave_days'] . '</td>';
            $html .= '<td>' . $item['absent_days'] . '</td>';
            $html .= '<td>' . $item['normal_days'] . '</td>';
            $html .= '<td>' . $item['total_work_hours'] . '</td>';
            $html .= '<td>' . $this->calculateAttendanceRate($item) . '%</td>';
            $html .= '<td>' . $this->calculateAverageHours($item) . 'h</td>';
            $html .= '</tr>';
        }
        $html .= '</tbody></table>';
        return $html;
    }
}

自动定时生成(cron任务)

创建自动执行脚本 cron_report.php

<?php
// cron_report.php
require_once 'config.php';
require_once 'AttendanceReportGenerator.php';
require_once 'ReportExporter.php';
// 上月1号到上月末(也可以传入特定日期)
$lastMonth = new DateTime('first day of last month');
$startDate = $lastMonth->format('Y-m-d');
$endDate = (new DateTime('last day of last month'))->format('Y-m-d');
// 生成统计
$generator = new AttendanceReportGenerator($pdo, $startDate, $endDate);
$reportData = $generator->getReport();
// 保存为Excel文件到指定目录
$exporter = new ReportExporter();
$filename = 'report_' . date('Y_m') . '.xlsx';
$filepath = __DIR__ . '/reports/' . $filename;
// 写入文件(注意:需要修改exporter支持保存到文件而不是直接输出)
$exporter->saveToFile($reportData, $filepath);
// 记录日志
file_put_contents('report_log.txt', date('Y-m-d H:i:s') . " 生成成功: $filename\n", FILE_APPEND);

设置cron(Linux服务器)

# 每天凌晨1点执行
0 1 * * * /usr/bin/php /path/to/project/cron_report.php

Windows计划任务(使用PHP CLI)

schtasks /create /tn "AttendanceReport" /tr "php.exe C:\project\cron_report.php" /sc daily /st 01:00

完整调用示例(Web页面)

<?php
// report_page.php
require_once 'config.php';
require_once 'AttendanceReportGenerator.php';
require_once 'ReportExporter.php';
$startDate = $_GET['start'] ?? date('Y-m-01');
$endDate = $_GET['end'] ?? date('Y-m-t');
$generator = new AttendanceReportGenerator($pdo, $startDate, $endDate);
$reportData = $generator->getReport();
?>
<!DOCTYPE html>
<html>
<head>考勤报表</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
</head>
<body>
    <div class="container mt-4">
        <h2>考勤统计报表(<?= $startDate ?> ~ <?= $endDate ?>)</h2>
        <form method="get" class="row mb-4">
            <div class="col">
                <input type="date" name="start" value="<?= $startDate ?>" class="form-control">
            </div>
            <div class="col">
                <input type="date" name="end" value="<?= $endDate ?>" class="form-control">
            </div>
            <div class="col">
                <button type="submit" class="btn btn-primary">查询</button>
                <a href="export.php?start=<?= $startDate ?>&end=<?= $endDate ?>" class="btn btn-success">导出Excel</a>
            </div>
        </form>
        <?php 
            $exporter = new ReportExporter();
            echo $exporter->generateHtmlTable($reportData); 
        ?>
    </div>
</body>
</html>

优化建议

功能 实现方式
缓存查询结果 使用Redis或文件缓存,避免频繁查库
大数据量处理 使用MySQL索引(user_id, date联合索引),分页查询
图表统计 结合Chart.js生成趋势图(月出勤率、迟到次数等)
多维度统计 按部门、职级、项目分组统计
异常标记 自动标记异常数据(重复打卡、未打卡等)

关键技术点总结

  1. 核心SQL:使用 LEFT JOIN + SUM(CASE WHEN) 实现多维度统计
  2. 时间计算TIMESTAMPDIFF 计算工时,BETWEEN 筛选日期范围
  3. 报表导出:推荐 PhpSpreadsheetSimpleXLSXGen
  4. 自动任务:cron定期执行,配合文件锁防止重复运行
  5. 错误处理:记录生成日志,发送邮件告警

如果需要更复杂的排班统计、加班计算、请假整合等功能,可以在此基础上扩展。

抱歉,评论功能暂时关闭!