本文目录导读:

- 方案一:服务器端脚本(Cron Job + 邮件/短信)
- 方案二:消息队列(Redis/Beanstalkd + Worker)
- 方案三:前端轮询或 WebSocket(配合后端 API)
- 方案四:第三方推送服务(极光、个推、UniPush)
- 选择建议
- 注意事项
在 PHP 项目中实现任务提醒功能,通常有几种主流的实现方式,选择哪一种取决于你的项目架构(是否使用框架)、服务器环境以及时效性要求(是立即提醒还是定时提醒)。
核心思路:发送通知(邮件、短信、站内信、推送)+ 定时触发(Cron、队列)。
以下是几种最常见且实用的实现方案:
服务器端脚本(Cron Job + 邮件/短信)
这是最传统、最可靠的方式,适用于“每天检查一次数据库,发送今日待办”的场景。
步骤:
-
数据库中存储任务和提醒时间
- 任务表(
tasks)中通常包含:id,user_id,title,due_date,remind_at,is_reminded(标记是否已提醒,避免重复发送)。
- 任务表(
-
编写 PHP 检查脚本
- 创建一个独立的 PHP 文件,
send_reminders.php。 - 脚本连接到数据库,查询所有
remind_at时间已到(或即将到来)、且is_reminded = 0的任务。 - 发送邮件(或短信),并将
is_reminded更新为 1。<?php // send_reminders.php require_once 'config/database.php';
$db = new PDO(...);
// 查询需要提醒的任务 (假设提前10分钟提醒) $stmt = $db->query("SELECT * FROM tasks WHERE remind_at <= DATE_ADD(NOW(), INTERVAL 10 MINUTE) AND is_reminded = 0"); $tasks = $stmt->fetchAll();
foreach ($tasks as $task) { // 发送邮件 mail($task['user_email'], '任务提醒: ' . $task['title'], '您的任务即将截止...');
// 标记已提醒 $update = $db->prepare("UPDATE tasks SET is_reminded = 1 WHERE id = ?"); $update->execute([$task['id']]); - 创建一个独立的 PHP 文件,
-
设置服务器定时任务 (Cron Job)
- 登录服务器(Linux),运行
crontab -e。 - 添加如下任务,让脚本每分钟执行一次:
* * * * * /usr/bin/php /path/to/your/project/send_reminders.php >> /dev/null 2>&1
- 优点:稳定、免费(除了邮件服务)。
- 缺点:只能精确到分钟;需要服务器管理权限;用户反馈不是实时的。
- 登录服务器(Linux),运行
消息队列(Redis/Beanstalkd + Worker)
适用于中大型项目,对实时性要求较高(如“5分钟后提醒我”),或者需要异步处理大量通知的场景。
工作流: 用户设置提醒 -> PHP将任务数据推入队列 -> 后台Worker进程从队列取出 -> 延迟消费(达到时间后) -> 发送通知。
使用 Laravel 框架示例(最流行):
-
创建任务
php artisan make:job SendTaskReminder
-
在控制器中调度任务
use App\Jobs\SendTaskReminder; use Carbon\Carbon; // 用户设定5分钟后提醒 $remindAt = Carbon::now()->addMinutes(5); SendTaskReminder::dispatch($task)->delay($remindAt);
-
Worker 监听
- 在服务器后台运行队列监听器:
php artisan queue:work --queue=default
- Laravel 会在
$remindAt时间到达时自动执行SendTaskReminder里的handle()方法,该方法负责发邮件/短信。
- 在服务器后台运行队列监听器:
-
替代方案(非 Laravel)
- 使用 Redis 的
Sorted Set:用时间戳作为 Score,自己实现延时消费。 - 使用 RabbitMQ 的
TTL(Time-To-Live)功能。
- 使用 Redis 的
前端轮询或 WebSocket(配合后端 API)
适用于用户登录后,在浏览器界面实时看到提醒(无需刷新页面)。
-
后端创建 API 接口
/api/notifications返回当前用户未读的提醒列表。// 响应当前用户未读提醒 header('Content-Type: application/json'); echo json_encode([ 'count' => 5, 'list' => ['任务A即将到期', '任务B已逾期'] ]);
-
前端 JavaScript 轮询
setInterval(async () => { const resp = await fetch('/api/notifications?user_id=1'); const data = await resp.json(); if (data.count > 0) { // 显示弹窗或音效 notifyUser(data.list); } }, 30000); // 每30秒检查一次 -
高级替代:WebSocket
- 使用 Pusher(第三方服务)、Laravel Echo Server 或 Swoole。
- 当 PHP 后端触发提醒(如方案二中的 Worker执行完),主动推送消息给特定用户的浏览器。
第三方推送服务(极光、个推、UniPush)
如果你需要精准的手机端 App 推送。
- PHP 端调用第三方 SDK。
- 用户触发设置提醒时,PHP 将任务信息发送给第三方服务器。
- 第三方服务器在指定时间(如果你使用了它们的定时推送功能)或立即推送到手机。
// 假设使用极光推送 $client = new \JPush\Client('app_key', 'master_secret'); $client->push() ->setPlatform('all') ->addAlias($user_id) // 推送给特定用户 ->iosNotification('您有一条新任务') ->send();
选择建议
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 小项目/个人工具 | 方案一 (Cron + Mail) | 简单、零成本、无需额外服务 |
| 企业级 Web 应用 | 方案二 (Laravel Queue + 邮件/SMS) | 高可用、可扩展、延时准确 |
| 需要实时 UI 更新 | 方案三 (轮询/WebSocket) | 用户体验好,配合后台队列 |
| 强时效性(手机App) | 方案四 (第三方推送) | 手机离线也能收到,集成简单 |
注意事项
- 避免重复提醒:数据库一定要有
is_reminded或status字段,否则 Cron 每分钟执行一次会把用户“炸”晕。 - 时区问题:用户可能在不同时区,数据库存储建议用 UTC 时间,前端展示时再转换。
- 性能:Cron 脚本不要写复杂逻辑(避免
sleep()),短时间执行完即可。 - 短信费用:国内短信(阿里云、腾讯云)每条几分钱,建议只做高优先级提醒(如逾期),邮件可用于批量提醒。
如果你能告诉我你的项目是原生 PHP、Laravel、ThinkPHP 还是其他框架,以及提醒方式是邮件、短信还是站内信,我可以给出更具体的代码示例。