برنامه ریزی وظایف
معرفی
در گذشته، ممکن است یک ورودی پیکربندی cron برای هر کاری که نیاز به برنامه ریزی روی سرور خود داشتید، نوشته باشید. با این حال، این می تواند به سرعت تبدیل به یک دردسر شود زیرا برنامه کاری شما دیگر در کنترل منبع نیست و باید برای مشاهده ورودی های cron موجود یا اضافه کردن ورودی های اضافی، SSH را به سرور خود وارد کنید.
زمانبندی فرمان لاراول یک رویکرد جدید برای مدیریت وظایف برنامه ریزی شده در
سرور شما ارائه می دهد. زمانبند به شما اجازه میدهد تا بهطور روان و واضح برنامه دستورات خود را در خود
برنامه لاراول تعریف کنید. هنگام استفاده از زمانبندی، تنها یک ورودی cron در سرور شما مورد نیاز است. برنامه
کاری شما در روش
app/Console/Kernel.php
فایل تعریف شده است
schedule
. برای کمک به شروع، یک مثال ساده در داخل متد تعریف شده است.
تعریف برنامه ها
شما می توانید تمام وظایف برنامه ریزی شده خود را در
schedule
متد کلاس برنامه خود تعریف کنید
App\Console\Kernel
. برای شروع، بیایید به یک مثال نگاه کنیم. در این مثال، ما تعطیلی را
برنامه ریزی می کنیم تا هر روز در نیمه شب تماس گرفته شود. در بسته شدن، یک کوئری پایگاه داده را برای پاک کردن
جدول اجرا می کنیم:
<?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{ /** * Define the application's command schedule. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule) { $schedule->call(function () { DB::table('recent_users')->delete(); })->daily(); }}
علاوه بر زمانبندی با استفاده از بستهها، میتوانید
اشیاء قابل فراخوانی را
نیز برنامهریزی کنید . اشیای فراخوانی کلاس های PHP ساده ای هستند که حاوی
__invoke
متد زیر هستند:
$schedule->call(new DeleteRecentUsers)->daily();
اگر می خواهید یک نمای کلی از وظایف برنامه ریزی شده خود و دفعه بعدی که
قرار است اجرا شوند، مشاهده کنید، می توانید از
schedule:list
دستور Artisan استفاده کنید:
php artisan schedule:list
زمانبندی دستورات صنعتگر
علاوه بر زمانبندی بسته شدن، میتوانید
دستورات Artisan
و دستورات سیستم را نیز برنامهریزی کنید. برای مثال، میتوانید از
command
روشی برای زمانبندی دستور Artisan با استفاده از نام یا کلاس دستور استفاده
کنید.
هنگام برنامهریزی دستورات Artisan با استفاده از نام کلاس دستور، میتوانید آرایهای از آرگومانهای خط فرمان اضافی را ارسال کنید که باید هنگام فراخوانی فرمان به آن ارائه شود:
use App\Console\Commands\SendEmailsCommand; $schedule->command('emails:send Taylor --force')->daily(); $schedule->command(SendEmailsCommand::class, ['Taylor', '--force'])->daily();
زمان بندی مشاغل در صف
این
job
روش ممکن است برای برنامه ریزی یک
کار در صف
استفاده شود . این روش روشی مناسب برای برنامهریزی مشاغل در صف بدون
استفاده از
call
روش تعریف بستهها برای صفبندی کار فراهم میکند:
use App\Jobs\Heartbeat; $schedule->job(new Heartbeat)->everyFiveMinutes();
آرگومان های دوم و سوم اختیاری ممکن است به روشی ارائه شود
job
که نام صف و اتصال صف را که باید برای صف بندی کار استفاده شود، مشخص می
کند:
use App\Jobs\Heartbeat; // Dispatch the job to the "heartbeats" queue on the "sqs" connection...$schedule->job(new Heartbeat, 'heartbeats', 'sqs')->everyFiveMinutes();
زمان بندی دستورات شل
این
exec
روش ممکن است برای صدور فرمان به سیستم عامل استفاده شود:
$schedule->exec('node /home/forge/script.js')->daily();
گزینه های فرکانس را برنامه ریزی کنید
ما قبلاً چند نمونه از نحوه پیکربندی یک کار را برای اجرا در فواصل زمانی مشخص دیدهایم. با این حال، فرکانسهای زمانبندی وظایف بسیار بیشتری وجود دارد که میتوانید به یک کار اختصاص دهید:
روش | شرح |
---|---|
->cron('* * * * *'); |
وظیفه را بر روی یک برنامه cron سفارشی اجرا کنید |
->everyMinute(); |
هر دقیقه کار را اجرا کنید |
->everyTwoMinutes(); |
کار را هر دو دقیقه یکبار اجرا کنید |
->everyThreeMinutes(); |
کار را هر سه دقیقه یکبار اجرا کنید |
->everyFourMinutes(); |
کار را هر چهار دقیقه یکبار اجرا کنید |
->everyFiveMinutes(); |
کار را هر پنج دقیقه یکبار اجرا کنید |
->everyTenMinutes(); |
کار را هر ده دقیقه یکبار اجرا کنید |
->everyFifteenMinutes(); |
کار را هر پانزده دقیقه اجرا کنید |
->everyThirtyMinutes(); |
کار را هر سی دقیقه یکبار اجرا کنید |
->hourly(); |
هر ساعت کار را اجرا کنید |
->hourlyAt(17); |
این کار را هر ساعت 17 دقیقه قبل از ساعت اجرا کنید |
->everyOddHour(); |
کار را هر ساعت فرد اجرا کنید |
->everyTwoHours(); |
کار را هر دو ساعت یکبار اجرا کنید |
->everyThreeHours(); |
کار را هر سه ساعت یکبار اجرا کنید |
->everyFourHours(); |
هر چهار ساعت یک بار کار را اجرا کنید |
->everySixHours(); |
این کار را هر شش ساعت یکبار اجرا کنید |
->daily(); |
کار را هر روز در نیمه شب اجرا کنید |
->dailyAt('13:00'); |
کار را هر روز ساعت 13:00 اجرا کنید |
->twiceDaily(1, 13); |
کار را هر روز در ساعت 1:00 و 13:00 اجرا کنید |
->twiceDailyAt(1, 13, 15); |
کار را روزانه در ساعت 1:15 و 13:15 اجرا کنید |
->weekly(); |
هر یکشنبه ساعت 00:00 این کار را اجرا کنید |
->weeklyOn(1, '8:00'); |
کار را هر هفته دوشنبه ساعت 8:00 اجرا کنید |
->monthly(); |
کار را در روز اول هر ماه ساعت 00:00 اجرا کنید |
->monthlyOn(4, '15:00'); |
کار را هر ماه در تاریخ 4 ساعت 15:00 اجرا کنید |
->twiceMonthly(1, 16, '13:00'); |
کار را ماهانه در روزهای 1 و 16 ساعت 13:00 اجرا کنید |
->lastDayOfMonth('15:00'); |
در آخرین روز ماه ساعت 15:00 کار را اجرا کنید |
->quarterly(); |
کار را در روز اول هر سه ماهه ساعت 00:00 اجرا کنید |
->quarterlyOn(4, '14:00'); |
این کار را هر سه ماهه چهارم در ساعت 14:00 انجام دهید |
->yearly(); |
کار را در اولین روز هر سال ساعت 00:00 انجام دهید |
->yearlyOn(6, 1, '17:00'); |
این کار را هر سال در 1 ژوئن ساعت 17:00 اجرا کنید |
->timezone('America/New_York'); |
منطقه زمانی کار را تنظیم کنید |
این روشها ممکن است با محدودیتهای اضافی ترکیب شوند تا برنامههای دقیقتری ایجاد کنند که فقط در روزهای خاصی از هفته اجرا میشوند. برای مثال، میتوانید دستوری را برای اجرای هفتگی در روز دوشنبه برنامهریزی کنید:
// Run once per week on Monday at 1 PM...$schedule->call(function () { //})->weekly()->mondays()->at('13:00'); // Run hourly from 8 AM to 5 PM on weekdays...$schedule->command('foo') ->weekdays() ->hourly() ->timezone('America/Chicago') ->between('8:00', '17:00');
فهرستی از محدودیتهای زمانبندی اضافی را میتوانید در زیر مشاهده کنید:
روش | شرح |
---|---|
->weekdays(); |
کار را به روزهای هفته محدود کنید |
->weekends(); |
کار را به آخر هفته ها محدود کنید |
->sundays(); |
کار را به یکشنبه محدود کنید |
->mondays(); |
کار را به دوشنبه محدود کنید |
->tuesdays(); |
کار را به سه شنبه محدود کنید |
->wednesdays(); |
کار را به چهارشنبه محدود کنید |
->thursdays(); |
کار را به پنجشنبه محدود کنید |
->fridays(); |
کار را به جمعه محدود کنید |
->saturdays(); |
کار را به شنبه محدود کنید |
->days(array|mixed); |
کار را به روزهای خاصی محدود کنید |
->between($startTime, $endTime); |
کار را بین زمان شروع و پایان محدود کنید |
->unlessBetween($startTime, $endTime); |
کار را محدود کنید تا بین زمان شروع و پایان اجرا نشود |
->when(Closure); |
کار را بر اساس آزمون حقیقت محدود کنید |
->environments($env); |
کار را به محیط های خاص محدود کنید |
محدودیت های روز
این
days
روش ممکن است برای محدود کردن اجرای یک کار به روزهای خاصی از هفته استفاده
شود. برای مثال، میتوانید دستوری را برای اجرای ساعتی در روزهای یکشنبه و چهارشنبه برنامهریزی کنید:
$schedule->command('emails:send') ->hourly() ->days([0, 3]);
از طرف دیگر، میتوانید از ثابتهای موجود در
Illuminate\Console\Scheduling\Schedule
کلاس هنگام تعیین روزهایی که یک وظیفه باید اجرا شود استفاده کنید:
use Illuminate\Console\Scheduling\Schedule; $schedule->command('emails:send') ->hourly() ->days([Schedule::SUNDAY, Schedule::WEDNESDAY]);
بین محدودیت های زمانی
این
between
روش ممکن است برای محدود کردن اجرای یک کار بر اساس زمان روز استفاده شود:
$schedule->command('emails:send') ->hourly() ->between('7:00', '22:00');
به طور مشابه، این
unlessBetween
روش می تواند برای حذف اجرای یک کار برای یک دوره زمانی استفاده شود:
$schedule->command('emails:send') ->hourly() ->unlessBetween('23:00', '4:00');
محدودیت های آزمون حقیقت
این
when
روش ممکن است برای محدود کردن اجرای یک کار بر اساس نتیجه یک آزمون صدق داده
شده استفاده شود. به عبارت دیگر، اگر بسته شدن داده شده برگردد
true
، تا زمانی که هیچ شرایط محدود کننده دیگری از اجرای وظیفه جلوگیری نکند،
وظیفه اجرا خواهد شد:
$schedule->command('emails:send')->daily()->when(function () { return true;});
روش
skip
ممکن است به صورت معکوس دیده شود
when
. اگر
skip
متد برگردد
true
، وظیفه برنامه ریزی شده اجرا نمی شود:
$schedule->command('emails:send')->daily()->skip(function () { return true;});
هنگام استفاده از
when
روشهای زنجیرهای، دستور زمانبندی شده تنها در صورتی اجرا میشود که همه
when
شرایط برگردند
true
.
محدودیت های محیطی
این
environments
روش ممکن است فقط برای اجرای وظایف در محیط های داده شده (همانطور که توسط
APP_ENV
متغیر محیطی
تعریف شده است ) استفاده شود:
$schedule->command('emails:send') ->daily() ->environments(['staging', 'production']);
محدوده های زمانی
با استفاده از
timezone
روش، می توانید تعیین کنید که زمان یک کار برنامه ریزی شده باید در یک منطقه
زمانی معین تفسیر شود:
$schedule->command('report:generate') ->timezone('America/New_York') ->at('2:00')
اگر به طور مکرر منطقه زمانی یکسانی را به همه وظایف برنامه ریزی شده خود
اختصاص می دهید، ممکن است بخواهید یک
scheduleTimezone
متد را در
App\Console\Kernel
کلاس خود تعریف کنید. این روش باید منطقه زمانی پیشفرض را که باید به همه
وظایف زمانبندی شده اختصاص داده شود، برگرداند:
/** * Get the timezone that should be used by default for scheduled events. * * @return \DateTimeZone|string|null */protected function scheduleTimezone(){ return 'America/Chicago';}
به یاد داشته باشید که برخی از مناطق زمانی از ساعت تابستانی استفاده می کنند. هنگامی که تغییر ساعت تابستانی رخ می دهد، کار برنامه ریزی شده شما ممکن است دو بار اجرا شود یا حتی اصلا اجرا نشود. به همین دلیل، توصیه می کنیم در صورت امکان از برنامه ریزی منطقه زمانی خودداری کنید.
جلوگیری از همپوشانی وظایف
بهطور پیشفرض، حتی اگر نمونه قبلی کار هنوز در حال اجرا باشد، کارهای
برنامهریزیشده اجرا میشوند. برای جلوگیری از این، می توانید از
withoutOverlapping
روش زیر استفاده کنید:
$schedule->command('emails:send')->withoutOverlapping();
در این مثال، اگر
emails:send
دستور Artisan
از قبل اجرا نشده باشد، هر دقیقه اجرا می شود. این
withoutOverlapping
روش مخصوصاً زمانی مفید است که وظایفی دارید که زمان اجرای آنها به شدت
متفاوت است و شما را از پیش بینی دقیق مدت زمان انجام یک کار باز می دارد.
در صورت نیاز، میتوانید تعیین کنید که چند دقیقه باید تا پایان قفل "بدون همپوشانی" بگذرد. به طور پیش فرض، قفل پس از 24 ساعت منقضی می شود:
$schedule->command('emails:send')->withoutOverlapping(10);
در پشت صحنه، این روش از
کش
withoutOverlapping
برنامه شما
برای به دست آوردن قفل استفاده می کند. در صورت لزوم می توانید این قفل های
کش را با استفاده از
دستور Artisan پاک کنید. این معمولاً فقط در صورتی ضروری است که یک کار به
دلیل یک مشکل غیرمنتظره سرور گیر کند.
schedule:clear-cache
اجرای وظایف روی یک سرور
برای استفاده از این ویژگی، برنامه شما باید از
database
,memcached
,dynamodb
یاredis
کش به عنوان درایور کش پیش فرض برنامه شما استفاده کند. علاوه بر این، همه سرورها باید با یک سرور حافظه مرکزی یکسان در ارتباط باشند.
اگر زمانبندی برنامه شما روی چندین سرور اجرا میشود، میتوانید یک کار زمانبندیشده را به اجرای تنها روی یک سرور محدود کنید. به عنوان مثال، فرض کنید یک کار برنامه ریزی شده دارید که هر جمعه شب یک گزارش جدید تولید می کند. اگر زمانبندی کار روی سه سرور کارگر اجرا شود، وظیفه برنامهریزیشده روی هر سه سرور اجرا میشود و گزارش را سه بار تولید میکند. خوب نیست!
برای نشان دادن اینکه وظیفه باید فقط روی یک سرور اجرا شود،
onOneServer
هنگام تعریف کار زمانبندی شده از روش استفاده کنید. اولین سروری که این
وظیفه را به دست می آورد، یک قفل اتمی روی کار ایمن می کند تا از اجرای همزمان همان کار توسط سایر سرورها
جلوگیری کند:
$schedule->command('report:generate') ->fridays() ->at('17:00') ->onOneServer();
نامگذاری مشاغل تک سرور
گاهی اوقات ممکن است لازم باشد که همان کار را برای ارسال با پارامترهای
مختلف برنامه ریزی کنید، در حالی که همچنان به لاراول دستور می دهید تا هر جایگشت کار را روی یک سرور واحد اجرا
کند. برای انجام این کار، میتوانید به هر تعریف زمانبندی یک نام منحصربهفرد از طریق
name
روش زیر اختصاص دهید:
$schedule->job(new CheckUptime('https://laravel.com')) ->name('check_uptime:laravel.com') ->everyFiveMinutes() ->onOneServer(); $schedule->job(new CheckUptime('https://vapor.laravel.com')) ->name('check_uptime:vapor.laravel.com') ->everyFiveMinutes() ->onOneServer();
به طور مشابه، بستههای برنامهریزیشده اگر قرار است روی یک سرور اجرا شوند، باید یک نام اختصاص دهند:
$schedule->call(fn () => User::resetApiRequestCount()) ->name('reset-api-request-count') ->daily() ->onOneServer();
وظایف پس زمینه
به طور پیش فرض، چندین کار برنامه ریزی شده به طور همزمان بر اساس ترتیبی که
در
schedule
روش شما تعریف شده اند به صورت متوالی اجرا می شوند. اگر کارهای طولانی مدت
دارید، ممکن است باعث شود کارهای بعدی خیلی دیرتر از زمان پیش بینی شده شروع شوند. اگر میخواهید وظایف را در
پسزمینه اجرا کنید تا همه آنها به طور همزمان اجرا شوند، میتوانید از
runInBackground
روش زیر استفاده کنید:
$schedule->command('analytics:report') ->daily() ->runInBackground();
این
runInBackground
روش فقط میتواند هنگام زمانبندی کارها از طریق متدهایcommand
و استفاده شودexec
.
حالت تعمیر و نگهداری
کارهای برنامه ریزی شده برنامه شما زمانی که برنامه در
حالت تعمیر و نگهداری
است اجرا نمی شود ، زیرا ما نمی خواهیم وظایف شما با تعمیر و نگهداری
ناتمامی که ممکن است در سرور خود انجام می دهید تداخل داشته باشد. با این حال، اگر میخواهید یک کار را مجبور
کنید حتی در حالت تعمیر و نگهداری اجرا شود، میتوانید
evenInMaintenanceMode
هنگام تعریف کار، متد را فراخوانی کنید:
$schedule->command('emails:send')->evenInMaintenanceMode();
اجرای برنامه زمانبندی
اکنون که نحوه تعریف وظایف برنامه ریزی شده را آموختیم، بیایید نحوه اجرای
واقعی آنها را در سرور خود مورد بحث قرار دهیم. دستور
schedule:run
Artisan تمام کارهای برنامه ریزی شده شما را ارزیابی می کند و تعیین می کند
که آیا آنها باید بر اساس زمان فعلی سرور اجرا شوند یا خیر.
بنابراین، هنگام استفاده از زمانبندی لاراول، فقط باید یک ورودی پیکربندی
cron را به سرور خود اضافه کنیم که
schedule:run
هر دقیقه دستور را اجرا میکند. اگر نمی دانید چگونه ورودی های cron را به
سرور خود اضافه کنید، از سرویسی مانند
Laravel Forge
استفاده کنید که می تواند ورودی های cron را برای شما مدیریت کند:
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
اجرای برنامه زمانبندی به صورت محلی
به طور معمول، ورودی cron زمانبندی را به ماشین توسعه محلی خود اضافه نمی
کنید. در عوض، می توانید از
schedule:work
دستور Artisan استفاده کنید. این دستور در پیش زمینه اجرا می شود و هر دقیقه
زمانبندی را فراخوانی می کند تا زمانی که دستور را خاتمه دهید:
php artisan schedule:work
خروجی وظیفه
زمانبند لاراول چندین روش راحت را برای کار با خروجی تولید شده توسط وظایف
برنامه ریزی شده ارائه می دهد. ابتدا، با استفاده از
sendOutputTo
روش، می توانید خروجی را برای بررسی بعدی به یک فایل ارسال کنید:
$schedule->command('emails:send') ->daily() ->sendOutputTo($filePath);
اگر می خواهید خروجی را به یک فایل معین اضافه کنید، می توانید از
appendOutputTo
روش زیر استفاده کنید:
$schedule->command('emails:send') ->daily() ->appendOutputTo($filePath);
با استفاده از این
emailOutputTo
روش، می توانید خروجی را به آدرس ایمیل دلخواه خود ایمیل کنید. قبل از ارسال
ایمیل خروجی یک کار، باید
سرویس های ایمیل
لاراول را پیکربندی کنید :
$schedule->command('report:generate') ->daily() ->sendOutputTo($filePath) ->emailOutputTo('taylor@example.com');
اگر میخواهید خروجی را فقط در صورتی ایمیل کنید که فرمان زمانبندی شده
Artisan یا سیستم با یک کد خروج غیر صفر خاتمه یابد، از
emailOutputOnFailure
روش زیر استفاده کنید:
$schedule->command('report:generate') ->daily() ->emailOutputOnFailure('taylor@example.com');
روش های
emailOutputTo
,emailOutputOnFailure
,sendOutputTo
, وappendOutputTo
منحصر به روشcommand
و هستندexec
.
قلاب های وظیفه
با استفاده از
before
و
after
متدها، می توانید کدی را مشخص کنید که قبل و بعد از اجرای وظیفه برنامه ریزی
شده اجرا شود:
$schedule->command('emails:send') ->daily() ->before(function () { // The task is about to execute... }) ->after(function () { // The task has executed... });
متدهای
onSuccess
و
onFailure
به شما این امکان را می دهند که کدی را مشخص کنید که در صورت موفقیت یا شکست
کار برنامه ریزی شده اجرا شود. خرابی نشان می دهد که دستور Artisan یا سیستم برنامه ریزی شده با یک کد خروج غیر
صفر خاتمه یافته است:
$schedule->command('emails:send') ->daily() ->onSuccess(function () { // The task succeeded... }) ->onFailure(function () { // The task failed... });
اگر خروجی از دستور شما در دسترس است، میتوانید
با تایپ کردن یک
نمونه به عنوان
آرگومان تعریف بسته شدن قلاب
after
، به آن در قلاب
onSuccess
یا قلاب خود دسترسی پیدا کنید:
onFailure
Illuminate\Support\Stringable
$output
use Illuminate\Support\Stringable; $schedule->command('emails:send') ->daily() ->onSuccess(function (Stringable $output) { // The task succeeded... }) ->onFailure(function (Stringable $output) { // The task failed... });
پینگ کردن URL ها
با استفاده از
pingBefore
و
thenPing
متدها، زمانبند میتواند به طور خودکار یک URL داده شده را قبل یا بعد از
اجرای یک کار پینگ کند. این روش برای اطلاع رسانی به یک سرویس خارجی مانند
Envoyer
مفید است که کار برنامه ریزی شده شما شروع شده یا اجرای آن به پایان رسیده
است:
$schedule->command('emails:send') ->daily() ->pingBefore($url) ->thenPing($url);
روشهای
pingBeforeIf
و
thenPingIf
تنها در صورتی میتوانند برای پینگ کردن یک URL معین استفاده شوند که یک شرط
مشخص باشد
true
:
$schedule->command('emails:send') ->daily() ->pingBeforeIf($condition, $url) ->thenPingIf($condition, $url);
تنها در صورت موفقیت یا عدم موفقیت کار، میتوان از روشهای و برای پینگ
کردن یک URL معین استفاده
کرد
pingOnSuccess
.
pingOnFailure
خرابی نشان می دهد که دستور Artisan یا سیستم برنامه ریزی شده با یک کد خروج
غیر صفر خاتمه یافته است:
$schedule->command('emails:send') ->daily() ->pingOnSuccess($successUrl) ->pingOnFailure($failureUrl);
همه روشهای پینگ به کتابخانه HTTP Guzzle نیاز دارند. Guzzle معمولاً در تمام پروژههای Laravel جدید به طور پیشفرض نصب میشود، اما، اگر بهطور تصادفی حذف شده باشد، میتوانید Guzzle را با استفاده از مدیر بسته Composer به صورت دستی در پروژه خود نصب کنید:
composer require guzzlehttp/guzzle
مناسبت ها
در صورت نیاز، می توانید به
رویدادهای
ارسال شده توسط زمانبندی گوش دهید. به طور معمول، نگاشت شنونده رویداد در
کلاس برنامه شما تعریف می شود
App\Providers\EventServiceProvider
:
/** * The event listener mappings for the application. * * @var array */protected $listen = [ 'Illuminate\Console\Events\ScheduledTaskStarting' => [ 'App\Listeners\LogScheduledTaskStarting', ], 'Illuminate\Console\Events\ScheduledTaskFinished' => [ 'App\Listeners\LogScheduledTaskFinished', ], 'Illuminate\Console\Events\ScheduledBackgroundTaskFinished' => [ 'App\Listeners\LogScheduledBackgroundTaskFinished', ], 'Illuminate\Console\Events\ScheduledTaskSkipped' => [ 'App\Listeners\LogScheduledTaskSkipped', ], 'Illuminate\Console\Events\ScheduledTaskFailed' => [ 'App\Listeners\LogScheduledTaskFailed', ],];