news 2026/6/20 3:27:05

PHP任务调度与定时执行框架

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PHP任务调度与定时执行框架

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任务调度器可以统一管理、记录日志、处理失败重试。适合需要复杂调度逻辑的场景。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/16 15:34:13

告别乱码!手把手教你用Qt Linguist搞定软件多语言翻译(附完整代码)

Qt国际化实战&#xff1a;从零构建多语言应用的完整指南第一次为Qt应用添加多语言支持时&#xff0c;我盯着满屏的tr()和ts文件不知所措。直到某个深夜&#xff0c;当我的应用界面终于能流畅切换中英文时&#xff0c;才明白国际化不是简单的文本替换&#xff0c;而是一套完整的…

作者头像 李华
网站建设 2026/6/20 23:42:37

教授背景强的香港EMBA项目客观测评|2026高管理性选型指南

一、引言&#xff1a;香港EMBA行业选型核心痛点随着大湾区企业数字化转型、全球化出海进程加速&#xff0c;香港EMBA凭借国际化资质、可留服认证、双语适配、地缘优势等特点&#xff0c;成为内地企业家、中高层高管深造的核心选择。当前香港EMBA市场项目品类繁杂&#xff0c;不…

作者头像 李华
网站建设 2026/6/19 11:19:07

AI工具每周更新速递

每周AI工具/模型更新报告&#xff08;2026.06.01-06.08&#xff09; &#x1f4ca; 本周核心更新概览 过去一周内&#xff0c;AI领域迎来多项重要更新&#xff0c;涵盖推理优化、Agent工具集、多模态模型、API降价等关键方向。以下是精选的6条核心动态&#xff1a; &#x1f5…

作者头像 李华
网站建设 2026/6/15 13:13:54

基于LPC54114与NxH3670的USB蓝牙音频Dongle设计与实现

1. 项目概述在无线音频的世界里&#xff0c;如何让一台传统的、只有有线接口的PC&#xff0c;也能享受到高品质、低延迟的蓝牙音频体验&#xff1f;这背后需要一个“翻译官”和“搬运工”。这个角色&#xff0c;就是今天要深入拆解的USB音频Dongle。它一端通过USB与PC相连&…

作者头像 李华