本文目录导读:

在PHP项目中实现逾期提醒功能,通常需要结合任务调度(Cron Job)、定时消息推送和数据库状态管理,以下是一个完整的实现方案:
数据库设计(核心字段)
假设你有 orders 表(订单),需要记录到期时间:
CREATE TABLE orders (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
due_date DATETIME NOT NULL, -- 截止日期
status ENUM('active', 'overdue') DEFAULT 'active',
remind_at DATETIME NULL, -- 上次提醒时间(防止重复提醒)
...
);
方案一:Cron Job + PHP脚本(最可靠)
步骤:
- 编写PHP检查脚本 (
cron_check_overdue.php) - 设置系统定时任务(Linux的cron)
PHP脚本示例:
<?php
// 连接数据库
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
// 查找所有逾期且未提醒的记录
$sql = "SELECT * FROM orders
WHERE due_date < NOW()
AND status = 'active'
AND (remind_at IS NULL OR remind_at < DATE_SUB(NOW(), INTERVAL 1 HOUR))";
$stmt = $pdo->query($sql);
$orders = $stmt->fetchAll();
foreach ($orders as $order) {
// 1. 发送提醒(邮件/短信/系统通知)
sendReminder($order['user_id'], $order['id']);
// 2. 更新状态为逾期,并记录提醒时间
$update = $pdo->prepare("UPDATE orders
SET status = 'overdue',
remind_at = NOW()
WHERE id = ?");
$update->execute([$order['id']]);
}
echo "Checked " . count($orders) . " overdue orders.";
?>
Cron配置(每分钟运行一次):
* * * * * /usr/bin/php /path/to/cron_check_overdue.php >> /var/log/overdue.log 2>&1
方案二:使用Laravel的任务调度
如果你使用Laravel框架,可以更优雅地实现:
在 app/Console/Kernel.php 中定义:
protected function schedule(Schedule $schedule)
{
$schedule->call(function () {
// 查询逾期订单
$overdueOrders = Order::where('due_date', '<', now())
->where('status', 'active')
->get();
foreach ($overdueOrders as $order) {
// 发送提醒
$order->user->notify(new OverdueReminder($order));
$order->update(['status' => 'overdue', 'remind_at' => now()]);
}
})->everyMinute(); // 或 dailyAt('08:00') 每天8点执行
}
提醒方式实现
A. 邮件提醒(使用PHPMailer或Laravel Mail)
function sendReminder($userId, $orderId) {
$user = getUser($userId); // 获取用户邮箱
$subject = "订单逾期提醒 - #{$orderId}";
$body = "您的订单 #{$orderId} 已逾期,请尽快处理!";
// 使用PHPMailer
$mail = new PHPMailer\PHPMailer\PHPMailer();
$mail->isSMTP();
$mail->Host = 'smtp.example.com';
$mail->SMTPAuth = true;
$mail->Username = 'your@email.com';
$mail->Password = 'password';
$mail->setFrom('noreply@example.com', '系统');
$mail->addAddress($user['email']);
$mail->Subject = $subject;
$mail->Body = $body;
$mail->send();
}
B. 短信提醒(集成第三方API,如阿里云短信)
// 使用阿里云SDK
use AlibabaCloud\Client\AlibabaCloud;
AlibabaCloud::accessKeyClient('accessKeyId', 'accessKeySecret')
->regionId('cn-hangzhou')
->asDefaultClient();
$result = AlibabaCloud::rpc()
->product('Dysmsapi')
->version('2017-05-25')
->action('SendSms')
->method('POST')
->options([
'query' => [
'PhoneNumbers' => $user['phone'],
'SignName' => '您的签名',
'TemplateCode' => 'SMS_123456',
'TemplateParam' => json_encode(['orderId' => $orderId]),
],
])
->request();
C. 系统站内通知(存入通知表)
// 创建通知记录
$pdo->prepare("INSERT INTO notifications (user_id, type, data, read_at)
VALUES (?, 'overdue_remind', ?, NULL)")
->execute([$userId, json_encode(['order_id' => $orderId])]);
方案三:实时提醒(WebSocket + 事件驱动)
对于需要即时提醒的场景(如用户登录后立刻看到):
- 使用 Redis Pub/Sub 或 Laravel Echo + Pusher
- 在Cron脚本执行后,发布事件到消息队列
- 前端通过WebSocket监听事件,立即弹出提醒
防重复提醒策略
- 字段控制:记录
last_remind_time,只对超过一定时间(如24小时)未提醒的记录发通知 - 状态机:将状态变为
overdue后不再重复提醒,除非状态重置 - 幂等性:在发送前检查
remind_at是否在最近N小时内
监控与日志
// 记录执行日志
file_put_contents('/var/log/overdue.log',
date('Y-m-d H:i:s') . " - Processed order #{$orderId}\n",
FILE_APPEND);
| 方法 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| Cron Job | 标准PHP项目 | 稳定可靠,不依赖框架 | 需要服务器crontab权限 |
| Laravel Scheduler | Laravel项目 | 配置简单 | 仅限Laravel |
| WebSocket | 需要即时通知 | 用户体验好 | 增加服务器复杂度 |
| 第三方服务 | 短信/邮件 | 无需自建基础设施 | 需要付费 |
推荐组合:Cron Job(定时检测) + 邮件/短信(通知)+ 数据库状态控制(防重复)。