本文目录导读:

- 命令行方式(最常用)
- 使用
pcntl扩展(仅 Unix/Linux) - 使用
Swoole扩展(高性能异步) - 使用 Workerman 或其他框架
- 纯 PHP 循环实现(不推荐)
- 使用队列系统(适合分布式)
- Web 方式(被动触发)
- 使用异步非阻塞方案
- 选择建议
- 注意事项
在 PHP 中实现定时器事件有多种方式,我为你整理了从简单到复杂的方案:
命令行方式(最常用)
PHP 脚本 + Cron Job(Linux/Mac)
// /path/to/your_script.php
<?php
// 要做的事情
file_put_contents('/var/log/cron.log', date('Y-m-d H:i:s') . " - 任务执行\n", FILE_APPEND);
# Crontab 配置(每5分钟执行) */5 * * * * /usr/bin/php /path/to/your_script.php # 每天凌晨2点执行 0 2 * * * /usr/bin/php /path/to/your_script.php # 每小时执行一次 0 * * * * /usr/bin/php /path/to/your_script.php
Windows 任务计划程序
:: 创建批处理文件 run_task.bat @echo off C:\php\php.exe D:\path\your_script.php
使用 pcntl 扩展(仅 Unix/Linux)
<?php
declare(ticks = 1);
function signal_handler($signal) {
echo "收到信号: $signal\n";
// 执行定时任务
sendEmail();
}
// 注册信号处理器
pcntl_signal(SIGALRM, "signal_handler");
while (true) {
// 设置10秒后的定时器
pcntl_alarm(10);
// 做一些其他工作
echo "程序运行中...\n";
sleep(1);
}
使用 Swoole 扩展(高性能异步)
<?php
// Swoole 定时器(毫秒级)
$timer = new Swoole\Timer;
// 每2秒执行一次
$timerId = $timer->tick(2000, function () {
echo "2秒定时器触发\n";
// 执行任务
processTask();
});
// 5秒后执行一次
$timer->after(5000, function () use ($timerId) {
echo "5秒后执行一次\n";
$timer->clear($timerId); // 清除定时器
});
使用 Workerman 或其他框架
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Timer;
use Workerman\Worker;
$worker = new Worker('tcp://0.0.0.0:2345');
$worker->onWorkerStart = function ($worker) {
// 每10秒执行一次
Timer::add(10, function () {
echo "定时任务执行\n";
// 你的业务逻辑
});
};
Worker::runAll();
纯 PHP 循环实现(不推荐)
<?php
// 简单的循环定时器
$interval = 5; // 5秒
$lastTime = time();
while (true) {
if (time() - $lastTime >= $interval) {
$lastTime = time();
echo "执行定时任务\n";
// 你的任务代码
}
sleep(1);
}
使用队列系统(适合分布式)
Laravel 计划任务
// app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
$schedule->call(function () {
// 每天执行的任务
DB::table('users')->update(['status' => 1]);
})->daily();
$schedule->command('emails:send')
->everyFiveMinutes();
}
Web 方式(被动触发)
<?php
// cron.php - 通过 web 请求触发
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['secret']) && $_POST['secret'] === 'your_secret') {
// 执行定时任务
processTasks();
echo "任务执行成功";
}
使用异步非阻塞方案
<?php
// ReactPHP 示例
require __DIR__ . '/vendor/autoload.php';
$loop = React\EventLoop\Factory::create();
$loop->addPeriodicTimer(5, function () {
echo "每5秒执行\n";
});
$loop->addTimer(60, function () {
echo "60秒后执行一次\n";
});
$loop->run();
选择建议
| 场景 | 推荐方案 |
|---|---|
| 常规定时任务 | Cron Job |
| 需要毫秒级精度 | Swoole / ReactPHP |
| 异步高性能场景 | Swoole / Workerman |
| 分布式系统 | 消息队列(Redis/Beanstalkd) |
| Web应用 | 框架自带的调度器 |
| 简单脚本 | sleep() + 循环 |
注意事项
-
PHP 执行超时:长时间运行的脚本可能触发
max_execution_time,需要设置:set_time_limit(0); // 不限制执行时间 ignore_user_abort(true); // 用户断开连接继续执行
-
内存管理:长时间运行要注意内存泄漏:
while (true) { // 执行任务 gc_collect_cycles(); // 定期清理垃圾 memory_get_usage(); // 监控内存 } -
日志记录:记录执行日志便于调试:
error_log("任务执行于 " . date('Y-m-d H:i:s'), 3, '/var/log/task.log');
选择哪种方案取决于你的具体需求:如果是简单的定时任务,Cron是最佳选择;如果需要高性能异步处理,建议使用Swoole。