本文目录导读:

我来帮你解释PHP值班的实现方法,PHP值班通常指的是定时任务(Cron Job)或轮班系统的实现。
PHP 定时任务(Crontab)
Linux 系统级Crontab
# 编辑定时任务 crontab -e # 示例:每天凌晨2点执行 0 2 * * * /usr/bin/php /path/to/script.php
PHP脚本示例
<?php
// cron_task.php
class CronTask {
private $logFile = '/var/log/cron.log';
public function run() {
$task = $this->getTaskForToday();
$result = $this->executeTask($task);
$this->log("Task: {$task}, Result: {$result}");
}
private function getTaskForToday() {
$dayOfWeek = date('w'); // 0=Sunday, 1=Monday, etc.
$tasks = [
0 => '备份数据库',
1 => '清理缓存',
2 => '发送报告',
3 => '更新索引',
4 => '数据统计',
5 => '安全检查',
6 => '系统维护'
];
return $tasks[$dayOfWeek] ?? '常规任务';
}
private function executeTask($task) {
// 执行具体任务逻辑
echo date('Y-m-d H:i:s') . " 执行: {$task}\n";
return true;
}
private function log($message) {
file_put_contents($this->logFile, date('Y-m-d H:i:s') . " {$message}\n", FILE_APPEND);
}
}
$cron = new CronTask();
$cron->run();
?>
值勤/值班轮班系统
简单轮班算法
<?php
// shift_system.php
class ShiftSystem {
private $staff = [
['id' => 1, 'name' => '张三'],
['id' => 2, 'name' => '李四'],
['id' => 3, 'name' => '王五'],
['id' => 4, 'name' => '赵六']
];
// 获取当天值班人
public function getTodayDuty() {
$totalStaff = count($this->staff);
$dayOfYear = date('z'); // 0-365
$index = $dayOfYear % $totalStaff;
return $this->staff[$index];
}
// 获取指定日期的值班人
public function getDutyByDate($date) {
$timestamp = strtotime($date);
$dayOfYear = date('z', $timestamp);
$totalStaff = count($this->staff);
$index = $dayOfYear % $totalStaff;
return $this->staff[$index];
}
// 获取值班表
public function getSchedule($startDate, $days = 30) {
$schedule = [];
$current = strtotime($startDate);
for ($i = 0; $i < $days; $i++) {
$date = date('Y-m-d', $current);
$dayOfYear = date('z', $current);
$index = $dayOfYear % count($this->staff);
$dayInfo = date('w', $current); // 0-6
// 周末跳过或不安排
if ($dayInfo == 0 || $dayInfo == 6) {
$schedule[] = [
'date' => $date,
'day' => date('l', $current),
'duty' => '休息',
'staff' => null
];
} else {
$schedule[] = [
'date' => $date,
'day' => date('l', $current),
'duty' => '值班',
'staff' => $this->staff[$index]
];
}
$current = strtotime('+1 day', $current);
}
return $schedule;
}
}
// 使用示例
$shift = new ShiftSystem();
echo "今天值班人: " . json_encode($shift->getTodayDuty()) . "\n";
echo "本月值班表: " . json_encode($shift->getSchedule(date('Y-m-d'), 30)) . "\n";
?>
带权重和特殊规则的排班系统
<?php
// advanced_shift.php
class AdvancedShiftSystem {
private $staff = [];
private $rules = [];
private $history = [];
public function __construct() {
$this->loadStaff();
$this->loadRules();
$this->loadHistory();
}
// 加载人员
private function loadStaff() {
$this->staff = [
['id' => 1, 'name' => '张三', 'weight' => 1, 'maxShifts' => 5],
['id' => 2, 'name' => '李四', 'weight' => 1, 'maxShifts' => 4],
['id' => 3, 'name' => '王五', 'weight' => 2, 'maxShifts' => 3],
['id' => 4, 'name' => '赵六', 'weight' => 1, 'maxShifts' => 5]
];
}
// 加载规则
private function loadRules() {
$this->rules = [
'max_consecutive' => 2, // 最大连续值班天数
'rest_after' => 1, // 值班后休息天数
'weekend_off' => true, // 周末是否休息
'holiday_off' => true // 节假日是否休息
];
}
// 智能排班
public function generateSchedule($startDate, $days = 30) {
$schedule = [];
$current = strtotime($startDate);
$staffLoad = [];
// 初始化人员负载
foreach ($this->staff as $s) {
$staffLoad[$s['id']] = 0;
}
for ($i = 0; $i < $days; $i++) {
$date = date('Y-m-d', $current);
$dutyStaff = $this->findBestStaff($date, $staffLoad, $schedule);
$schedule[] = [
'date' => $date,
'day' => date('l', $current),
'staff' => $dutyStaff,
'isWeekend' => in_array(date('w', $current), [0, 6])
];
if ($dutyStaff) {
$staffLoad[$dutyStaff['id']]++;
}
$current = strtotime('+1 day', $current);
}
return $schedule;
}
// 查找最佳值班人员
private function findBestStaff($date, &$staffLoad, $schedule) {
$available = [];
foreach ($this->staff as $staff) {
// 检查是否达到最大值班数
if ($staffLoad[$staff['id']] >= $staff['maxShifts']) {
continue;
}
// 检查是否连续值班过多
$consecutive = $this->getConsecutiveDuty($staff['id'], $date, $schedule);
if ($consecutive >= $this->rules['max_consecutive']) {
continue;
}
// 检查是否在休息期
$lastDuty = $this->getLastDutyDate($staff['id'], $schedule);
if ($lastDuty && (strtotime($date) - strtotime($lastDuty)) / 86400 <= $this->rules['rest_after']) {
continue;
}
$available[] = $staff;
}
// 按权重排序
usort($available, function($a, $b) use ($staffLoad) {
$scoreA = $a['weight'] * 10 - $staffLoad[$a['id']];
$scoreB = $b['weight'] * 10 - $staffLoad[$b['id']];
return $scoreB - $scoreA;
});
return $available[0] ?? null;
}
// 获取连续值班天数
private function getConsecutiveDuty($staffId, $date, $schedule) {
$count = 0;
$current = strtotime($date . ' -1 day');
for ($i = 0; $i < $this->rules['max_consecutive']; $i++) {
$prevDate = date('Y-m-d', $current);
$prevSchedules = array_filter($schedule, function($s) use ($prevDate, $staffId) {
return $s['date'] == $prevDate && $s['staff']['id'] == $staffId;
});
if (!empty($prevSchedules)) {
$count++;
} else {
break;
}
$current = strtotime('-1 day', $current);
}
return $count;
}
// 获取上次值班日期
private function getLastDutyDate($staffId, $schedule) {
foreach (array_reverse($schedule) as $s) {
if ($s['staff'] && $s['staff']['id'] == $staffId) {
return $s['date'];
}
}
return null;
}
// 加载历史记录
private function loadHistory() {
// 从数据库或文件加载历史排班记录
}
}
// 使用示例
$scheduler = new AdvancedShiftSystem();
$schedule = $scheduler->generateSchedule(date('Y-m-d'), 7);
echo "未来7天排班:\n";
foreach ($schedule as $day) {
echo "{$day['date']} ({$day['day']}): ";
if ($day['staff']) {
echo "{$day['staff']['name']} 值班";
} else {
echo "休息";
}
echo "\n";
}
?>
数据库存储版
数据库表结构
CREATE TABLE duty_schedule (
id INT AUTO_INCREMENT PRIMARY KEY,
staff_id INT NOT NULL,
duty_date DATE NOT NULL,
shift_type VARCHAR(50), -- morning, afternoon, night
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY unique_duty (staff_id, duty_date)
);
CREATE TABLE staff (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(100),
weight INT DEFAULT 1,
is_active TINYINT(1) DEFAULT 1
);
PHP数据库操作
<?php
// db_shift.php
class DbShiftSystem {
private $db;
public function __construct() {
$this->db = new PDO('mysql:host=localhost;dbname=shift_system', 'root', 'password');
}
// 生成并保存值班表
public function generateAndSave($startDate, $days = 30) {
$schedule = $this->generateSchedule($startDate, $days);
$stmt = $this->db->prepare("
INSERT INTO duty_schedule (staff_id, duty_date, shift_type)
VALUES (?, ?, ?)
");
foreach ($schedule as $day) {
if ($day['staff']) {
$stmt->execute([
$day['staff']['id'],
$day['date'],
'full'
]);
}
}
}
// 获取某天值班人员
public function getDutyByDate($date) {
$stmt = $this->db->prepare("
SELECT s.*, d.shift_type
FROM duty_schedule d
JOIN staff s ON d.staff_id = s.id
WHERE d.duty_date = ?
");
$stmt->execute([$date]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
}
实际应用建议
-
使用成熟库:
-
监控和日志:
// 记录值班日志 function logDuty($staffId, $action) { $log = date('Y-m-d H:i:s') . " | Staff: {$staffId} | Action: {$action}\n"; file_put_contents('/var/log/duty_log.txt', $log, FILE_APPEND); } -
通知提醒:
// 发送值班提醒邮件 function sendDutyReminder($staff, $dutyDate) { $subject = "值班提醒 - {$dutyDate}"; $message = "{$staff['name']},您在 {$dutyDate} 值班,请准时到岗。"; mail($staff['email'], $subject, $message); }
需要更具体的功能(如轮班倒班、节假日处理、多语言等),请告诉我具体需求!