PHP 怎么PHP 值班

wen PHP项目 2

本文目录导读:

PHP 怎么PHP 值班

  1. PHP 定时任务(Crontab)
  2. 值勤/值班轮班系统
  3. 数据库存储版
  4. 实际应用建议

我来帮你解释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);
    }
}

实际应用建议

  1. 使用成熟库

  2. 监控和日志

    // 记录值班日志
    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);
    }
  3. 通知提醒

    // 发送值班提醒邮件
    function sendDutyReminder($staff, $dutyDate) {
     $subject = "值班提醒 - {$dutyDate}";
     $message = "{$staff['name']},您在 {$dutyDate} 值班,请准时到岗。";
     mail($staff['email'], $subject, $message);
    }

需要更具体的功能(如轮班倒班、节假日处理、多语言等),请告诉我具体需求!

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