在以前,開發(fā)者需要為每一個(gè)需要調(diào)度的任務(wù)編寫一個(gè) Cron 條目,這是很讓人頭疼的事。你的任務(wù)調(diào)度不在源碼控制中,你必須使用 SSH 登錄到服務(wù)器然后添加這些 Cron 條目。Laravel 命令調(diào)度器允許你平滑而又富有表現(xiàn)力地在 Laravel 中定義命令調(diào)度,并且服務(wù)器上只需要一個(gè) Cron 條目即可。
任務(wù)調(diào)度定義在 app/Console/Kernel.php
文件的 schedule
方法中,該方法中已經(jīng)包含了一個(gè)示例。你可以自由地添加你需要的調(diào)度任務(wù)到 Schedule
對(duì)象。
下面是你唯一需要添加到服務(wù)器的 Cron 條目:
* * * * * php /path/to/artisan schedule:run 1>> /dev/null 2>&1
該 Cron 將會(huì)每分鐘調(diào)用 Laravel 命令調(diào)度,然后,Laravel 評(píng)估你的調(diào)度任務(wù)并運(yùn)行到期的任務(wù)。
你可以在 App\Console\Kernel
類的 schedule
方法中定義所有調(diào)度任務(wù)。開始之前,讓我們看一個(gè)調(diào)度任務(wù)的例子,在這個(gè)例子中,我們將會(huì)在每天午夜調(diào)度一個(gè)被調(diào)用的閉包。在這個(gè)閉包中我們將會(huì)執(zhí)行一個(gè)數(shù)據(jù)庫(kù)查詢來清空表:
<?php
namespace App\Console;
use DB;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel{
/**
* 應(yīng)用提供的 Artisan 命令
*
* @var array
*/
protected $commands = [
'App\Console\Commands\Inspire',
];
/**
* 定義應(yīng)用的命令調(diào)度
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->call(function () {
DB::table('recent_users')->delete();
})->daily();
}
}
除了調(diào)度閉包調(diào)用外,還可以調(diào)度 Artisan 命令和操作系統(tǒng)命令。例如,可以使用 command
方法來調(diào)度一個(gè) Artisan 命令:
$schedule->command('emails:send --force')->daily();
exec
命令可用于發(fā)送命令到操作系統(tǒng):
$schedule->exec('node /home/forge/script.js')->daily();
當(dāng)然,你可以分配多種調(diào)度到任務(wù):
http://wiki.jikexueyuan.com/project/laravel-5.1/images/8.png" alt="" />
這些方法可以和額外的約束一起聯(lián)合起來創(chuàng)建一周特定時(shí)間運(yùn)行的更加細(xì)粒度的調(diào)度,例如,要每周一調(diào)度一個(gè)命令:
$schedule->call(function () {
// 每周星期一13:00運(yùn)行一次...
})->weekly()->mondays()->at('13:00');
下面是額外的調(diào)度約束列表:
http://wiki.jikexueyuan.com/project/laravel-5.1/images/9.png" alt="" />
when
方法用于限制任務(wù)在通過給定測(cè)試之后運(yùn)行。換句話說,如果給定閉包返回 true
,只要沒有其它約束條件阻止任務(wù)運(yùn)行,該任務(wù)就會(huì)執(zhí)行:
$schedule->command('emails:send')->daily()->when(function () {
return true;
});
默認(rèn)情況下,即使前一個(gè)任務(wù)仍然在運(yùn)行調(diào)度任務(wù)也會(huì)運(yùn)行,要避免這樣的情況,可使用 withoutOverlapping
方法:
$schedule->command('emails:send')->withoutOverlapping();
在本例中,Artisan 命令 emails:send
每分鐘都會(huì)運(yùn)行,如果該命令沒有在運(yùn)行的話。如果你的任務(wù)在執(zhí)行時(shí)經(jīng)常大幅度的變化,那么 withoutOverlapping
方法就非常有用,你不必再去預(yù)測(cè)給定任務(wù)到底要消耗多長(zhǎng)時(shí)間。
Laravel 調(diào)度器為處理調(diào)度任務(wù)輸出提供了多個(gè)方便的方法。首先,使用 sendOutputTo
方法,你可以發(fā)送輸出到文件以便稍后檢查:
$schedule->command('emails:send')
->daily()
->sendOutputTo($filePath);
使用 emailOutputTo
方法,你可以將輸出發(fā)送到電子郵件,注意輸出必須首先通過 sendOutputTo
方法發(fā)送到文件。還有,使用電子郵件發(fā)送任務(wù)輸出之前,應(yīng)該配置 Laravel 的電子郵件服務(wù):
$schedule->command('foo')
->daily()
->sendOutputTo($filePath)
->emailOutputTo('foo@example.com');
注意:emailOutputTo
和 sendOutputTo
方法只對(duì) command
方法有效,不支持 call
方法。
使用 before
和 after
方法,你可以指定在調(diào)度任務(wù)完成之前和之后要執(zhí)行的代碼:
$schedule->command('emails:send')
->daily()
->before(function () {
// Task is about to start...
})
->after(function () {
// Task is complete...
});
使用 pingBefore
和 thenPing
方法,調(diào)度器可以在任務(wù)完成之前和之后自動(dòng) ping 給定的 URL。該方法在通知外部服務(wù)時(shí)很有用,例如 Laravel Envoyer,在調(diào)度任務(wù)開始或完成的時(shí)候:
$schedule->command('emails:send')
->daily()
->pingBefore($url)
->thenPing($url);
使用 pingBefore($url)
或 thenPing($url)
特性需要安裝 HTTP 庫(kù) Guzzle,可以在 composer.json
文件中添加如下行來安裝 Guzzle 到項(xiàng)目:
"guzzlehttp/guzzle": "~5.3|~6.0"