PHP任务调度与定时执行框架
定时任务是后台系统的常见需求。除了用cron,也可以在PHP中实现任务调度器。今天说说PHP任务调度的实现。
任务调度器的基本实现。
```php
class TaskScheduler
{
private array $tasks = [];
private string $logFile;
public function __construct(string $logFile = '/var/log/scheduler.log')
{
$this->logFile = $logFile;
}
public function call(callable $task, array $schedule, string $name = ''): void
{
$this->tasks[] = [
'task' => $task,
'schedule' => $schedule,
'name' => $name ?: 'Task_' . count($this->tasks),
'lastRun' => 0,
];
}
public function everyMinute(callable $task, string $name = ''): void
{
$this->call($task, ['interval' => 60], $name);
}
public function everyFiveMinutes(callable $task, string $name = ''): void
{
$this->call($task, ['interval' => 300], $name);
}
public function dailyAt(callable $task, string $time, string $name = ''): void
{
[$hour, $minute] = explode(':', $time);
$this->call($task, ['hour' => (int)$hour, 'minute' => (int)$minute], $name);
}
public function run(): void
{
$now = time();
$date = getdate($now);
foreach ($this->tasks as &$task) {
if ($this->shouldRun($task, $date, $now)) {
$this->execute($task);
$task['lastRun'] = $now;
}
}
unset($task);
}
private function shouldRun(array $task, array $date, int $now): bool
{
$schedule = $task['schedule'];
if (isset($schedule['interval'])) {
return ($now - $task['lastRun']) >= $schedule['interval'];
}
$hourMatch = !isset($schedule['hour']) || $date['hours'] === $schedule['hour'];
$minuteMatch = !isset($schedule['minute']) || $date['minutes'] === $schedule['minute'];
return $hourMatch && $minuteMatch && ($now - $task['lastRun'] >= 60);
}
private function execute(array &$task): void
{
$start = microtime(true);
$name = $task['name'];
try {
echo "[{$this->timestamp()}] 执行: {$name}\n";
($task['task'])();
$duration = round((microtime(true) - $start) * 1000, 2);
echo " [{$this->timestamp()}] 完成 ({$duration}ms)\n";
} catch (Exception $e) {
echo " [{$this->timestamp()}] 失败: {$e->getMessage()}\n";
}
}
private function timestamp(): string
{
return date('Y-m-d H:i:s');
}
}
$scheduler = new TaskScheduler();
$scheduler->everyMinute(function () {
echo "每分钟心跳\n";
}, 'heartbeat');
$scheduler->everyFiveMinutes(function () {
echo "清理缓存\n";
}, 'cache_clean');
$scheduler->dailyAt(function () {
echo "生成日报\n";
}, '02:00', 'daily_report');
$scheduler->run();
?>
基于Cron表达式的调度。
```php
class CronScheduler
{
private array $tasks = [];
public function add(string $name, string $cronExpression, callable $task): void
{
$this->tasks[] = compact('name', 'cronExpression', 'task');
}
public function run(): void
{
$now = new DateTime();
foreach ($this->tasks as $task) {
if ($this->matchCron($task['cronExpression'], $now)) {
echo "执行: {$task['name']}\n";
($task['task'])();
}
}
}
private function matchCron(string $expression, DateTime $date): bool
{
$parts = preg_split('/\s+/', $expression);
if (count($parts) !== 5) return false;
$minute = (int)$date->format('i');
$hour = (int)$date->format('G');
$day = (int)$date->format('j');
$month = (int)$date->format('n');
$weekday = (int)$date->format('w');
return $this->fieldMatch($parts[0], $minute, 0, 59)
&& $this->fieldMatch($parts[1], $hour, 0, 23)
&& $this->fieldMatch($parts[2], $day, 1, 31)
&& $this->fieldMatch($parts[3], $month, 1, 12)
&& $this->fieldMatch($parts[4], $weekday, 0, 7);
}
private function fieldMatch(string $field, int $value, int $min, int $max): bool
{
if ($field === '*') return true;
if (str_contains($field, ',')) {
return in_array($value, array_map('intval', explode(',', $field)));
}
if (str_contains($field, '-')) {
[$start, $end] = explode('-', $field);
return $value >= (int)$start && $value <= (int)$end;
}
if (str_contains($field, '/')) {
[, $step] = explode('/', $field);
return $value % (int)$step === 0;
}
return (int)$field === $value;
}
}
?>
任务调度器让定时任务的管理更方便。相比直接使用cron,PHP任务调度器可以统一管理、记录日志、处理失败重试。适合需要复杂调度逻辑的场景。
PHP任务调度与定时执行框架
张小明
前端开发工程师
告别乱码!手把手教你用Qt Linguist搞定软件多语言翻译(附完整代码)
Qt国际化实战:从零构建多语言应用的完整指南第一次为Qt应用添加多语言支持时,我盯着满屏的tr()和ts文件不知所措。直到某个深夜,当我的应用界面终于能流畅切换中英文时,才明白国际化不是简单的文本替换,而是一套完整的…
教授背景强的香港EMBA项目客观测评|2026高管理性选型指南
一、引言:香港EMBA行业选型核心痛点随着大湾区企业数字化转型、全球化出海进程加速,香港EMBA凭借国际化资质、可留服认证、双语适配、地缘优势等特点,成为内地企业家、中高层高管深造的核心选择。当前香港EMBA市场项目品类繁杂,不…
AI工具每周更新速递
每周AI工具/模型更新报告(2026.06.01-06.08) 📊 本周核心更新概览 过去一周内,AI领域迎来多项重要更新,涵盖推理优化、Agent工具集、多模态模型、API降价等关键方向。以下是精选的6条核心动态: ǵ…
不只是教程:用YOLOv5s/m/l/x在VisDrone2019上跑分对比,帮你选出性价比最高的模型
YOLOv5模型选型实战:VisDrone2019数据集上的精度与效率博弈 在无人机巡检、智慧交通等实际场景中,目标检测模型的选型往往需要在精度和效率之间找到最佳平衡点。本文将以VisDrone2019数据集为测试平台,对YOLOv5系列模型(s/m/l/x)进行全面评测…
别再让Solr 5.x-8.3.1成为突破口:手把手复现CVE-2019-17558并配置安全加固
Solr安全实战:从CVE-2019-17558漏洞验证到企业级防护体系构建当企业搜索服务突然成为攻击者的跳板时,运维团队的每一秒都价值千金。2019年曝光的Velocity模板注入漏洞(CVE-2019-17558)至今仍在影响大量未升级的Solr实例࿰…
基于LPC54114与NxH3670的USB蓝牙音频Dongle设计与实现
1. 项目概述在无线音频的世界里,如何让一台传统的、只有有线接口的PC,也能享受到高品质、低延迟的蓝牙音频体验?这背后需要一个“翻译官”和“搬运工”。这个角色,就是今天要深入拆解的USB音频Dongle。它一端通过USB与PC相连&…