本文目录导读:

要为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生成趋势图(月出勤率、迟到次数等) |
| 多维度统计 | 按部门、职级、项目分组统计 |
| 异常标记 | 自动标记异常数据(重复打卡、未打卡等) |
关键技术点总结
- 核心SQL:使用
LEFT JOIN+SUM(CASE WHEN)实现多维度统计 - 时间计算:
TIMESTAMPDIFF计算工时,BETWEEN筛选日期范围 - 报表导出:推荐
PhpSpreadsheet或SimpleXLSXGen - 自动任务:cron定期执行,配合文件锁防止重复运行
- 错误处理:记录生成日志,发送邮件告警
如果需要更复杂的排班统计、加班计算、请假整合等功能,可以在此基础上扩展。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播