在本文中,我們將介紹 Laravel Web 框架的一項令人興奮的功能—任務調度。我們將了解 Laravel 如何讓您管理應用程式中的排程任務。此外,我們最終還將創建自己的自訂計劃任務以用於演示目的。
Laravel 框架可讓您設定排程任務,這樣您就不必擔心在系統層級設定它們。您可以在設定排程任務時擺脫複雜的 cron 語法,因為 Laravel 允許您以使用者友好的方式定義它們。
我們將首先介紹如何設定傳統的 cron 作業,然後我們將探索 Laravel 實現它的方式。在本文的後半部分,我們將透過建立幾個自訂計畫任務來嘗試一下,這些任務應該提供對該主題的實際洞察。
在日常應用程式開發中,您經常需要定期執行某些腳本或命令。如果您使用 *nix 系統,您可能知道 cron 作業處理這些命令。另一方面,它們在基於 Windows 的系統上稱為排程任務。
讓我們快速瀏覽一下基於 *nix 的 cron 作業的簡單範例。
*/5 * * * * /web/statistics.sh
非常簡單-它每五分鐘運行一次statistics.sh檔案!
雖然這是一個非常簡單的範例,但您通常需要實作更複雜的用例。複雜的系統要求您定義以不同時間間隔執行的多個 cron 作業。
讓我們看看複雜的 Web 應用程式必須在後端定期執行的一些任務。
正如您所看到的,有很多東西等待定期並以不同的時間間隔運行。如果您是經驗豐富的系統管理員,則可以輕鬆地為所有這些任務定義 cron 作業,但有時我們作為開發人員希望有更簡單的方法。
幸運的是,Laravel 附帶了一個內建的任務調度 API,它允許您以前所未有的方式定義排程任務。是的,下一節就是關於 Laravel 任務調度的基礎。
在前面的部分中,我們介紹了設定 cron 作業的傳統方法。在本節中,我們將在任務排程 API 的上下文中詳細介紹 Laravel。
在我們繼續之前,需要了解的重要一點是 Laravel 提供的調度功能就像任何其他功能一樣,不會自動呼叫。因此,如果您認為不需要在系統層級執行任何操作,那麼我想說您就不走運了。
事實上,如果您希望使用 Laravel 調度系統,您應該做的第一件事就是設定每分鐘執行一次的 cron 作業,並呼叫以下程式碼片段中顯示的 artisan
命令。
* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1
上面的 artisan
指令呼叫 Laravel 調度程序,然後執行應用程式中定義的所有待處理的 cron 作業。
當然,我們還沒有看到如何在 Laravel 應用程式中定義規劃任務,這就是我們接下來要深入討論的內容。
這是 App\Console\Kernel
類別的 schedule
方法,如果您希望定義特定於應用程式的排程任務,則需要使用該方法。
繼續取得 app/Console/Kernel.php 檔案的內容。
<?php namespace App\Console; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; class Kernel extends ConsoleKernel { /** * The Artisan commands provided by your application. * * @var array */ protected $commands = [ // ]; /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { // $schedule->command('inspire')->hourly(); } /** * Register the commands for the application. * * @return void */ protected function commands() { $this->load(__DIR__.'/Commands'); require base_path('routes/console.php'); } }
正如您所看到的,核心程式碼本身提供了一個有用的範例。在上面的範例中,Laravel 每小時執行 inspire
artisan
指令。不覺得文法一開始就很直覺嗎?
事實上,Laravel 允許您透過多種不同的方式定義排程任務:
artisan
指令。 此外,還有大量內建的調度頻率可供您選擇:
事實上,我想說它提供了一套完整的例程,因此您無需接觸 shell 即可建立自訂 cron 作業!
是的,我看得出您很想知道如何實現您的自訂計劃任務,這也是我在文章開頭所承諾的。
正如我們所討論的,Laravel 允許您以不同的方式定義計劃任務。讓我們逐一了解其工作原理。
調度 API 提供了 call
方法,該方法可讓您執行可呼叫函數或閉包函數。讓我們使用以下程式碼修改 app/Console/Kernel.php 檔案。
<?php namespace App\Console; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; use Illuminate\Support\Facades\DB; class Kernel extends ConsoleKernel { /** * The Artisan commands provided by your application. * * @var array */ protected $commands = [ // ]; /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { // the call method $schedule->call(function () { $posts = DB::table('posts') ->select('user_id', DB::raw('count(*) as total_posts')) ->groupBy('user_id') ->get(); foreach($posts as $post) { DB::table('users_statistics') ->where('user_id', $post->user_id) ->update(['total_posts' => $post->total_posts]); } })->everyThirtyMinutes(); } /** * Register the commands for the application. * * @return void */ protected function commands() { $this->load(__DIR__.'/Commands'); require base_path('routes/console.php'); } }
如您所见,我们将闭包函数作为 call
方法的第一个参数传递。另外,我们将频率设置为每 30 分钟一次,因此它将每 30 分钟执行一次关闭函数!
在我们的示例中,我们计算每个用户的帖子总数并相应地更新 statistics
表。
artisan
命令除了闭包或可调用之外,您还可以安排一个 artisan
命令,该命令将按一定的时间间隔执行。事实上,它应该是优于闭包的首选方法,因为它同时提供了更好的代码组织和可重用性。
继续使用以下内容修改 app/Console/Kernel.php 文件的内容。
<?php namespace App\Console; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; use Illuminate\Support\Facades\DB; class Kernel extends ConsoleKernel { /** * The Artisan commands provided by your application. * * @var array */ protected $commands = [ 'App\Console\Commands\UserStatistics' ]; /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { $schedule->command('statistics:user')->everyThirtyMinutes(); } /** * Register the commands for the application. * * @return void */ protected function commands() { $this->load(__DIR__.'/Commands'); require base_path('routes/console.php'); } }
这是 command
方法,如果您希望安排 artisan
命令,如上面的代码片段所示,您可以使用该方法。您需要传递 artisan
命令签名作为 command
方法的第一个参数。
当然,你还需要在app/Console/Commands/UserStatistics.php处定义相应的artisan
命令。
<?php namespace App\Console\Commands; use Illuminate\Console\Command; use Illuminate\Support\Facades\DB; class UserStatistics extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'statistics:user'; /** * The console command description. * * @var string */ protected $description = 'Update user statistics'; /** * Create a new command instance. * * @return void */ public function __construct() { parent::__construct(); } /** * Execute the console command. * * @return mixed */ public function handle() { // calculate new statistics $posts = DB::table('posts') ->select('user_id', DB::raw('count(*) as total_posts')) ->groupBy('user_id') ->get(); // update statistics table foreach($posts as $post) { DB::table('users_statistics') ->where('user_id', $post->user_id) ->update(['total_posts' => $post->total_posts]); } } }
exec
命令我们可以说到目前为止我们讨论的方法是特定于 Laravel 应用程序本身的。此外,Laravel 还允许您安排 shell 命令,以便您也可以运行外部应用程序。
让我们通过一个简单的示例来演示如何每天备份数据库。
<?php namespace App\Console; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; class Kernel extends ConsoleKernel { /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { // exec method $host = config('database.connections.mysql.host'); $username = config('database.connections.mysql.username'); $password = config('database.connections.mysql.password'); $database = config('database.connections.mysql.database'); $schedule->exec("mysqldump -h {$host} -u {$username} -p{$password} {$database}") ->daily() ->sendOutputTo('/backups/daily_backup.sql'); } }
从代码中可以明显看出,您需要使用调度程序的 exec
方法,并且需要将要运行的命令作为其第一个参数传递。
除此之外,我们还使用了 sendOutputTo
方法,它允许您收集命令的输出。另一方面,有一个方法,emailOutputTo
,它允许您通过电子邮件发送输出内容!
在本节中,我们将了解如何防止任务重叠。假设您已经定义了一个任务,并且您想要确保如果它已经在运行,Laravel 不应该运行同一任务的另一个实例。默认情况下,Laravel 将始终开始运行计划任务,即使同一任务的前一个实例已经在运行但尚未完成。
那么让我们看看如何避免重叠计划任务。
$schedule->command('statistics:user')->everyThirtyMinutes()->withoutOverlapping();
正如你所看到的,你只需要使用 withoutOverlapping
方法来确保 Laravel 不会与已经运行的任务重叠。默认情况下,Laravel 重叠任务之前的锁定时间为 24 小时。如果您想覆盖它,可以按照以下代码片段所示进行操作。
$schedule->command('statistics:user')->everyThirtyMinutes()->withoutOverlapping(30);
在上面的示例中,Laravel 等待 30 分钟才清除重叠锁。
如果您同时安排多个任务,Laravel 会按顺序运行它们。因此,如果您有一个需要很长时间才能执行的任务,则下一个计划任务将不得不等待很长时间。为了避免这种情况,您可以在后台执行此类任务。
让我们快速看一下下面的示例,了解如何定义后台任务。
$schedule->command('statistics:user')->daily()->runInBackground();
如您所见,您可以使用 runInBackground
方法来定义后台任务。
今天,我们了解了 Laravel Web 框架中的任务调度 API。看到它如何轻松地管理需要定期运行的任务真是令人着迷。
在文章的开头,我们讨论了传统的设置计划任务的方式,接下来我们介绍了 Laravel 的设置方式。在本文的后半部分,我们通过几个实际示例来演示任务调度概念。
我希望您喜欢这篇文章,并且您应该对在 Laravel 中设置计划任务更有信心。对于那些刚刚开始使用 Laravel 或希望通过扩展来扩展您的知识、网站或应用程序的人,我们在 Envato Market 上提供了多种您可以学习的内容。
以上是Laravel中的任務調度的詳細內容。更多資訊請關注PHP中文網其他相關文章!