本文目录导读:

我来给你介绍几种 PHP 排班通知的实现方案,根据你的需求复杂度来选择:
简单轮班制(最基础)
<?php
class SimpleShiftScheduler {
private $employees = ['张三', '李四', '王五', '赵六'];
private $shifts = ['早班', '中班', '晚班'];
public function generateWeeklySchedule($startDate) {
$schedule = [];
$shiftIndex = 0;
$employeeIndex = 0;
for ($i = 0; $i < 7; $i++) {
$date = date('Y-m-d', strtotime("$startDate + $i days"));
$schedule[$date] = [
'employee' => $this->employees[$employeeIndex % count($this->employees)],
'shift' => $this->shifts[$shiftIndex % count($this->shifts)]
];
$shiftIndex++;
$employeeIndex = (int)($shiftIndex / 2);
}
return $schedule;
}
}
数据库驱动排班系统
<?php
class DatabaseScheduler {
private $pdo;
public function __construct($pdo) {
$this->pdo = $pdo;
}
// 生成排班表
public function generateSchedule($startDate, $endDate, $shiftPattern = [0,1,2,0,1,2]) {
$sql = "INSERT INTO schedules (employee_id, shift_date, shift_type, created_at) VALUES (?, ?, ?, NOW())";
$stmt = $this->pdo->prepare($sql);
$employees = $this->getAvailableEmployees();
$currentDate = $startDate;
while ($currentDate <= $endDate) {
foreach ($employees as $key => $employee) {
$shiftIndex = date('N', strtotime($currentDate)) - 1;
$shiftType = $this->getShiftType($employee['id'], $currentDate);
// 检查是否有请假或不可用
if (!$this->isEmployeeAvailable($employee['id'], $currentDate)) {
continue;
}
// 分配班次
$stmt->execute([
$employee['id'],
$currentDate,
$shiftType
]);
}
$currentDate = date('Y-m-d', strtotime($currentDate . ' +1 day'));
}
return $this->getSchedule($startDate, $endDate);
}
// 发送排班通知
public function sendScheduleNotification($scheduleId) {
$schedule = $this->getScheduleById($scheduleId);
if (!$schedule) {
return ['success' => false, 'message' => '排班记录不存在'];
}
// 获取员工联系方式
$employee = $this->getEmployeeContact($schedule['employee_id']);
// 发送短信通知
$smsResult = $this->sendSMSNotification(
$employee['phone'],
"您的排班通知:{$schedule['shift_date']} {$schedule['shift_type']},请准时到岗"
);
// 发送邮件通知(可选)
if (!empty($employee['email'])) {
$this->sendEmailNotification(
$employee['email'],
'排班通知',
$this->formatEmailContent($schedule)
);
}
return ['success' => true];
}
// 批量发送通知
public function sendBulkNotifications($date) {
$schedules = $this->getSchedulesByDate($date);
$results = [];
foreach ($schedules as $schedule) {
$results[] = [
'employee' => $schedule['employee_name'],
'result' => $this->sendScheduleNotification($schedule['id'])
];
}
return $results;
}
private function sendSMSNotification($phone, $message) {
// 使用短信服务商API,如阿里云、腾讯云等
$api = new SmsService();
return $api->send($phone, $message);
}
private function sendEmailNotification($email, $subject, $content) {
// 使用PHP Mailer或第三方邮件服务
$mail = new PHPMailer();
$mail->addAddress($email);
$mail->Subject = $subject;
$mail->Body = $content;
return $mail->send();
}
}
高级智能排班(带规则约束)
<?php
class SmartScheduler {
private $rules = [];
private $employeeAvailability = [];
// 添加排班规则
public function addRule($ruleName, $callback) {
$this->rules[$ruleName] = $callback;
}
// 设置员工可用时间
public function setEmployeeAvailability($employeeId, $availability) {
$this->employeeAvailability[$employeeId] = $availability;
}
// 生成最优排班方案
public function generateOptimalSchedule($startDate, $days, $shiftsPerDay) {
$schedule = [];
$allEmployees = $this->getAllEmployees();
for ($i = 0; $i < $days; $i++) {
$date = date('Y-m-d', strtotime("$startDate + $i days"));
$dailySchedule = [];
for ($shift = 0; $shift < $shiftsPerDay; $shift++) {
$candidates = $this->findCandidates($date, $shift, $allEmployees);
if ($candidates) {
// 按优先级选择最佳人选
$selected = $this->selectBestCandidate($candidates, [
'date' => $date,
'shift' => $shift,
'schedule' => $schedule
]);
$dailySchedule[] = [
'date' => $date,
'shift' => $shift,
'employee' => $selected,
'status' => 'confirmed'
];
}
}
$schedule[] = $dailySchedule;
}
return $schedule;
}
private function findCandidates($date, $shift, $employees) {
$candidates = [];
foreach ($employees as $employee) {
// 检查员工是否可用
if (!$this->isAvailable($employee['id'], $date, $shift)) {
continue;
}
// 检查连续工作天数
if ($this->hasOverwork($employee['id'], $date)) {
continue;
}
// 计算推荐分数
$score = $this->calculateScore($employee, $date, $shift);
$candidates[] = array_merge($employee, ['score' => $score]);
}
// 按分数排序
usort($candidates, function($a, $b) {
return $b['score'] <=> $a['score'];
});
return $candidates;
}
private function calculateScore($employee, $date, $shift) {
$score = 100; // 基础分
// 根据历史出勤率加分
$attendanceRate = $this->getAttendanceRate($employee['id']);
$score += $attendanceRate * 10;
// 技能匹配加分
if ($this->hasRequiredSkill($employee['id'], $shift)) {
$score += 20;
}
// 连续工作扣分
$consecutiveDays = $this->getConsecutiveWorkDays($employee['id']);
$score -= $consecutiveDays * 5;
// 加班扣分
if ($this->isOvertime($employee['id'], $date)) {
$score -= 15;
}
// 员工偏好加分
$preference = $this->getShiftPreference($employee['id']);
if ($preference == $shift) {
$score += 10;
}
return $score;
}
private function isAvailable($employeeId, $date, $shift) {
// 检查员工是否被设置为不可用
if (!isset($this->employeeAvailability[$employeeId])) {
return true;
}
$availability = $this->employeeAvailability[$employeeId];
$dayOfWeek = date('N', strtotime($date));
return isset($availability[$dayOfWeek][$shift])
&& $availability[$dayOfWeek][$shift] === true;
}
}
发送通知的完整实现
<?php
class ScheduleNotifier {
private $scheduleData;
public function __construct($scheduleData) {
$this->scheduleData = $scheduleData;
}
public function notifyViaMultipleChannels() {
$notifications = [];
foreach ($this->scheduleData as $schedule) {
$channels = $this->getPreferredChannels($schedule['employee_id']);
foreach ($channels as $channel) {
$result = $this->sendViaChannel($channel, $schedule);
$notifications[] = [
'employee' => $schedule['employee_name'],
'channel' => $channel,
'status' => $result ? 'success' : 'failed',
'timestamp' => date('Y-m-d H:i:s')
];
}
}
return $notifications;
}
private function sendViaChannel($channel, $schedule) {
$message = $this->formatScheduleMessage($schedule);
switch ($channel) {
case 'wechat':
return $this->sendWechatMessage($schedule['wechat_id'], $message);
case 'sms':
return $this->sendSMS($schedule['phone'], $message);
case 'email':
return $this->sendEmail($schedule['email'], '排班通知', $message);
case 'app_notification':
return $this->sendAppNotification($schedule['user_id'], $message);
default:
return false;
}
}
private function formatScheduleMessage($schedule) {
return sprintf(
"【排班通知】%s\n员工:%s\n班次:%s\n时间:%s-%s\n备注:%s\n请准时到岗,如有问题请提前联系管理人员。",
$schedule['shift_date'],
$schedule['employee_name'],
$schedule['shift_type'],
$schedule['start_time'],
$schedule['end_time'],
$schedule['remarks'] ?? '无'
);
}
// 微信通知(通过企业微信/公众号)
private function sendWechatMessage($openId, $message) {
$url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";
$data = [
'touser' => $openId,
'template_id' => 'YOUR_TEMPLATE_ID',
'data' => [
'content' => ['value' => $message]
]
];
return $this->curlPost($url, json_encode($data));
}
// 手机短信
private function sendSMS($phone, $message) {
// 使用阿里云短信或腾讯云短信
$config = [
'access_key' => 'YOUR_ACCESS_KEY',
'secret' => 'YOUR_SECRET',
'sign_name' => '你的签名',
'template_code' => 'SMS_12345678'
];
$sms = new AliyunSms();
return $sms->send($phone, $message, $config);
}
// 邮件通知
private function sendEmail($to, $subject, $content) {
$mail = new PHPMailer();
$mail->isSMTP();
$mail->Host = 'smtp.example.com';
$mail->SMTPAuth = true;
$mail->Username = 'your-email@example.com';
$mail->Password = 'your-password';
$mail->setFrom('from@example.com', '排班系统');
$mail->addAddress($to);
$mail->Subject = $subject;
$mail->Body = $content;
return $mail->send();
}
// APP推送(使用极光推送等)
private function sendAppNotification($userId, $message) {
$jpush = new JPush('app_key', 'master_secret');
return $jpush->push()
->setPlatform('ios', 'android')
->addAlias($userId)
->setNotificationAlert($message)
->send();
}
}
使用示例
<?php
// 初始化排班系统
$scheduler = new SmartScheduler();
// 设置规则
$scheduler->addRule('max_consecutive_days', function($employeeId) {
// 最多连续工作5天
return $this->getConsecutiveWorkDays($employeeId) < 5;
});
// 设置员工可用时间
$scheduler->setEmployeeAvailability(1, [
1 => [true, true, true], // 周一所有班次
2 => [true, false, true], // 周二中班不排
// ...
]);
// 生成下周排班
$startDate = date('Y-m-d', strtotime('next Monday'));
$schedule = $scheduler->generateOptimalSchedule($startDate, 7, 3);
// 发送通知
$notifier = new ScheduleNotifier($schedule);
$results = $notifier->notifyViaMultipleChannels();
// 记录日志
foreach ($results as $result) {
echo "通知 {$result['employee']} 成功,渠道:{$result['channel']}\n";
}
推荐使用第三方案例
如果你不想从零开发,可以查看这些开源项目:
- SimpleSchedule - 轻量级排班系统
- ShiftScheduler - 支持多种班次类型
- SmartRota - 智能排班+通知
需要完整项目代码或者有其他功能需求(比如请假管理、调班申请等),我可以帮你进一步完善!