使用 Laravel 调度器的技巧

发布日期 作者

Tips for Using Laravel’s Scheduler image

Laravel 的 任务调度 功能文档齐全,并提供流畅的 API,让您拥有 cron 的全部功能。文档涵盖了您快速上手调度器所需的大部分内容,但我想谈谈与 cron 相关的几个底层概念,这将有助于您更深入地了解 Laravel 如何确定哪些计划任务应该运行。

了解 Cron

在 Laravel 调度器的基础上,您需要了解如何通过 Cron 的有点让人困惑的语法在服务器上安排任务。

在我们更深入地了解 cron 并学习可以用来熟悉 cron 的资源之前,让我们先看看调度器的基本组成部分。

首先,您需要通过 Laravel 应用程序的 App\Console\Kernel::schedule() 方法定义计划任务

/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')
// ->hourly();
}

您可以使用此方法定义所有需要运行的计划任务。Schedule 实例方法 command() 返回 Illuminate\Console\Scheduling\Event 类的一个实例。

如果您想调试事件类的一个实例,您可以像以下示例一样进行转储

$event = $schedule->command('inspire')
->hourly();
 
dd($event->expression); // "0 * * * *"

要触发此方法,请运行 artisan

> php artisan
"0 * * * *"

事件实例有一个 expression 属性,该属性在流畅的 API 调用之后存储任务的 cron 表示形式。

请记住此示例的值,因为我们将在下面讨论 cron。

Laravel 使用调度器的流畅 API(在本例中为 hourly() 方法)屏蔽了 cron,但了解 cron 将有助于您更好地理解幕后发生的事情。

以下文本表示应阐明 cron 的工作原理,如果您不熟悉(即使您熟悉,我认为这仍然有用)

# Use the hash sign to prefix a comment
# +---------------- minute (0 - 59)
# | +------------- hour (0 - 23)
# | | +---------- day of month (1 - 31)
# | | | +------- month (1 - 12)
# | | | | +---- day of week (0 - 7) (Sunday=0 or 7)
# | | | | |
# * * * * * command to be executed
#-----------------------------------------------------------

使用上面的示例“0 * * * *”,此任务将在每一天的每一个月中的每一天的每一天的每小时的零分钟标记处运行。

Cron 还有一些其他格式,可能会让人感到奇怪,例如使用 Laravel 的 quarterly() 方法生成的表达式

0 0 1 1-12/3 *

每季度运行一次任务意味着它将在 1 月到 12 月的每三个月的第一天的 00:00 运行。奇怪的 1-12/3 语法称为“步长值”,可以与范围结合使用。 crontab – Linux 手册页 将步长值描述如下

步长值可以与范围结合使用。在范围后加“”指定了在范围内以数字的值为间隔跳过。例如,“0-23/2”可以在小时字段中使用,以指定每隔一个小时执行命令(V7 标准中的替代方法是“0,2,4,6,8,10,12,14,16,18,20,22”)。步长也可以在星号之后使用,因此如果您想说“每两个小时”,只需使用“*/2”。

我建议您阅读手册页,或者至少将其放在手边,以便在您需要更好地了解任务的底层 cron 调度时可以参考。

了解调度事件 API

Laravel 有些很棒的流畅 API,允许您将多个方法调用链接在一起。调度 Event 类也不例外。但是,您可能使用的一些组合存在一些细微差别。

以下示例可以更好地说明:假设我们要让一个命令每小时运行一次,但仅在星期一、星期三和星期五运行

$schedule->command('inspire')
->hourly()
->mondays()
->wednesdays()
->fridays();

您可能认为上面的命令实现了正确的 cron,但事实并非如此。在上面的示例中,最后调用的“day”方法是 fridays(),因此,cron 如下所示

0 * * * 5

上面的任务将每小时运行一次,但仅在星期五运行。

在我向您展示实现我们想要的功能的正确方法调用之前,让我们先看看 Event::fridays() 方法。fridays() 方法(以及许多其他方法)来自 Laravel 的 ManagesFrequencies 特性

/**
* Schedule the event to run only on Fridays.
*
* @return $this
*/
public function fridays()
{
return $this->days(5);
}

此方法调用特性上的另一个方法 days(),该方法在撰写本文时看起来像这样

/**
* Set the days of the week the command should run on.
*
* @param array|mixed $days
* @return $this
*/
public function days($days)
{
$days = is_array($days) ? $days : func_get_args();
 
return $this->spliceIntoPosition(5, implode(',', $days));
}

您可以查看 spliceIntoPosition() 的工作原理,但所有“day”方法都会互相覆盖,因此最后调用的方法会保留。

以下是如何使用 Laravel 的流畅 API 编写正确的调度

$schedule->command('inspire')
->hourly()
->days([1, 3, 5]);

调试此任务实例会产生以下表达式

0 * * * 1,3,5

Bingo!

直接使用 Cron

大多数情况下,我认为大多数人更喜欢使用 Laravel 的流畅 API。但是,Event 任务包括一个 cron() 方法来直接设置表达式

$schedule->command('inspire')
->cron('0 * * * 1,3,5');

我认为 Laravel 的流畅 API 是定义命令更易读的方式,但如果您更喜欢使用 cron 语法,您可以使用此方法获得 cron 的全部功能。

Crontab Guru

对于高级用例以及更好地了解计划任务的运行方式,请考虑调试底层 cron 表达式,并使用诸如 crontab.guru – cron 调度表达式编辑器 之类的工具。

Paul Redmond photo

Laravel 新闻的撰稿人。全栈 Web 开发人员和作者。

Cube

Laravel 时事通讯

加入 40,000 多名其他开发人员,绝不错过新的技巧、教程等等。

Laravel Forge logo

Laravel Forge

轻松创建和管理您的服务器,并在几秒钟内部署您的 Laravel 应用程序。

Laravel Forge
Tinkerwell logo

Tinkerwell

Laravel 开发人员必备的代码运行器。使用 AI、自动完成和对本地和生产环境的即时反馈进行调试。

Tinkerwell
No Compromises logo

无妥协

来自 No Compromises 播客的两位经验丰富的开发人员 Joel 和 Aaron 现已可以为您的 Laravel 项目聘用。⬧ 固定价格为每月 7500 美元。⬧ 没有冗长的销售流程。⬧ 没有合同。⬧ 100% 退款保证。

无妥协
Kirschbaum logo

Kirschbaum

提供创新和稳定性,确保您的 Web 应用程序取得成功。

Kirschbaum
Shift logo

Shift

正在运行旧版本的 Laravel?立即使用自动化的 Laravel 升级和代码现代化功能,让您的应用程序保持新鲜。

Shift
Bacancy logo

Bacancy

仅需每月 2500 美元,即可为您的项目配备一位经验丰富的 Laravel 开发人员(拥有 4-6 年的经验)。获得 160 小时的专业知识和 15 天的无风险试用期。立即安排通话!

Bacancy
Lucky Media logo

Lucky Media

立即获得好运 - Laravel 开发的理想选择,拥有十多年的经验!

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar:Laravel 电子商务

Laravel 的电子商务。一个开源包,将现代无头电子商务功能的力量带到 Laravel。

Lunar:Laravel 电子商务
LaraJobs logo

LaraJobs

官方的 Laravel 招聘网站

LaraJobs
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit:Laravel SaaS 启动套件

SaaSykit 是一个 Laravel SaaS 启动套件,它包含运行现代 SaaS 所需的所有功能。付款、漂亮的结账、管理面板、用户仪表板、身份验证、现成的组件、统计数据、博客、文档等等。

SaaSykit:Laravel SaaS 启动套件
Rector logo

Rector

您无缝升级 Laravel、降低成本和加速创新的合作伙伴,助力公司取得成功

Rector
MongoDB logo

MongoDB

通过将 MongoDB 和 Laravel 强力整合,您可以增强 PHP 应用程序,让开发者轻松高效地构建应用程序。支持事务性、搜索、分析和移动用例,同时使用熟悉的 Eloquent API。探索灵活、现代的 MongoDB 数据库如何改变您的 Laravel 应用程序。

MongoDB
Maska is a Simple Zero-dependency Input Mask Library image

Maska 是一个简单的、零依赖的输入掩码库

阅读文章
Add Swagger UI to Your Laravel Application image

将 Swagger UI 添加到您的 Laravel 应用程序

阅读文章
Assert the Exact JSON Structure of a Response in Laravel 11.19 image

在 Laravel 11.19 中断言响应的精确 JSON 结构

阅读文章
Build SSH Apps with PHP and Laravel Prompts image

使用 PHP 和 Laravel Prompts 构建 SSH 应用程序

阅读文章
Building fast, fuzzy site search with Laravel and Typesense image

使用 Laravel 和 Typesense 构建快速、模糊的网站搜索

阅读文章
Add Comments to your Laravel Application with the Commenter Package image

使用 Commenter 包将评论添加到您的 Laravel 应用程序

阅读文章