参阅 安装指南 以获取有关如何设置调度任务的说明。
过去,开发人员会为他们需要调度的每个任务生成一个 Cron 条目。然而,这有时会是一个麻烦。你的任务调度不再位于版本控制中,而且你必须通过 SSH 连接到你的服务器来添加 Cron 条目。命令调度器允许你流畅且富有表达力地在应用程序内部定义你的命令调度,而且你的服务器上只需要一个 Cron 条目。
您可以通过覆盖 插件注册文件 中的 registerSchedule 方法来定义所有定时任务。 该方法将接受一个 $schedule 参数并用于定义命令及其执行频率。
首先,让我们看一个任务调度的例子。在此示例中,我们将调度一个 Closure,使其每天午夜被调用。在 Closure 中,我们将执行一个数据库查询来清空一个表:
class Plugin extends PluginBase
{
// ...
public function registerSchedule($schedule)
{
$schedule->call(function () {
Db::table('recent_users')->delete();
})->daily();
}
}除了调度 Closure 调用外,你还可以调度 控制台命令 以及操作系统命令。例如,你可以使用 command 方法来调度控制台命令:
$schedule->command('cache:clear')->daily();该 exec 命令可用于向操作系统发出命令:
$schedule->exec('node /home/acme/script.js')->daily();当然,你可以给你的任务分配多种排程:
| Method | Description |
|---|---|
->cron('* * * * *'); | Run the task on a custom Cron schedule |
->everyMinute(); | Run the task every minute |
->everyFiveMinutes(); | Run the task every five minutes |
->everyTenMinutes(); | Run the task every ten minutes |
->everyThirtyMinutes(); | Run the task every thirty minutes |
->hourly(); | Run the task every hour |
->daily(); | Run the task every day at midnight |
->dailyAt('13:00'); | Run the task every day at 13:00 |
->twiceDaily(1, 13); | Run the task daily at 1:00 & 13:00 |
->weekly(); | Run the task every week |
->monthly(); | Run the task every month |
这些方法可以结合额外的约束,以创建甚至更加精细的调度,使其仅在一周中的特定日期运行。 例如,要调度一个命令每周一运行:
$schedule->call(function () {
// Runs once a week on Monday at 13:00...
})->weekly()->mondays()->at('13:00');以下是附加日程约束的列表:
| Method | Description |
|---|---|
->weekdays(); | Limit the task to weekdays |
->sundays(); | Limit the task to Sunday |
->mondays(); | Limit the task to Monday |
->tuesdays(); | Limit the task to Tuesday |
->wednesdays(); | Limit the task to Wednesday |
->thursdays(); | Limit the task to Thursday |
->fridays(); | Limit the task to Friday |
->saturdays(); | Limit the task to Saturday |
->when(Closure); | Limit the task based on a truth test |
when 方法可以用来根据给定真值测试的结果来限制任务的执行。换句话说,如果给定的 Closure 返回 true,只要没有其他限制条件阻止任务运行,任务就会执行:
$schedule->command('emails:send')->daily()->when(function () {
return true;
});默认情况下,即使该任务的上一个实例仍在运行,计划任务也会运行。为了防止这种情况,您可以使用 withoutOverlapping 方法:
$schedule->command('emails:send')->withoutOverlapping();在此示例中,emails:send 控制台命令如果尚未运行,将每分钟运行一次。withoutOverlapping 方法特别有用,如果您有执行时间差异很大的任务,它可以避免您需要精确预测给定任务将花费多长时间。
调度器提供了几种便捷的方法,用于处理由调度任务生成的输出。首先,使用 sendOutputTo 方法,你可以将输出发送到一个文件,以便后续检查。
$schedule->command('emails:send')
->daily()
->sendOutputTo($filePath);使用 emailOutputTo 方法,您可以将输出通过电子邮件发送到您选择的电子邮件地址。请注意,输出必须首先使用 sendOutputTo 方法发送到文件。此外,在通过电子邮件发送任务输出之前,您应该配置邮件服务。
$schedule->command('foo')
->daily()
->sendOutputTo($filePath)
->emailOutputTo('foo@example.tld');
emailOutputTo和sendOutputTo方法专属于command方法,且不支持call。
使用 before 和 after 方法,你可以指定代码在预定任务完成之前和之后执行:
$schedule->command('emails:send')
->daily()
->before(function () {
// Task is about to start...
})
->after(function () {
// Task is complete...
});使用 pingBefore 和 thenPing 方法,调度器可以自动 ping 指定的 URL,在任务完成之前或之后。此方法有助于通知外部服务,您的计划任务正在开始或已完成:
$schedule->command('emails:send')
->daily()
->pingBefore($url)
->thenPing($url);