برنامه ریزی وظایف
معرفی
در گذشته، ممکن است برای هر وظیفه ای که برای برنامه ریزی روی سرور خود نیاز داشتید، یک ورودی Cron ایجاد کرده باشید. با این حال، این می تواند به سرعت تبدیل به یک دردسر شود، زیرا برنامه کاری شما دیگر در کنترل منبع نیست و برای اضافه کردن ورودی های اضافی Cron باید به سرور خود SSH کنید.
برنامه زمانبندی فرمان لاراول به شما این امکان را می دهد که به طور روان و واضح برنامه دستورات خود را در خود لاراول تعریف کنید. هنگام استفاده از زمانبندی، تنها یک ورودی Cron در سرور شما مورد نیاز است. برنامه کاری شما در روش
app/Console/Kernel.php
فایل تعریف شده است
schedule
. برای کمک به شروع، یک مثال ساده در داخل متد تعریف شده است.
شروع برنامه زمانبندی
هنگام استفاده از زمانبندی، فقط باید ورودی Cron زیر را به سرور خود اضافه کنید. اگر نمی دانید چگونه ورودی های Cron را به سرور خود اضافه کنید، از سرویسی مانند Laravel Forge استفاده کنید که می تواند ورودی های Cron را برای شما مدیریت کند:
* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
این کرون هر دقیقه زمانبندی فرمان لاراول را فراخوانی می کند. هنگامی که
schedule:run
دستور اجرا می شود، لاراول وظایف برنامه ریزی شده شما را ارزیابی می کند و وظایفی را که موعد مقرر انجام می شود اجرا می کند.
تعریف برنامه ها
شما می توانید تمام وظایف برنامه ریزی شده خود را در
schedule
متد کلاس تعریف کنید
App\Console\Kernel
. برای شروع، به مثالی از زمان بندی یک کار نگاه می کنیم. در این مثال، ما برنامه ای را برنامه ریزی می کنیم
Closure
که هر روز در نیمه شب تماس گرفته شود. در داخل
Closure
یک کوئری پایگاه داده برای پاک کردن جدول اجرا می کنیم:
<?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) { $schedule->call(function () { DB::table('recent_users')->delete(); })->daily(); }}
علاوه بر زمانبندی با استفاده از Closures، میتوانید از
اشیاء فراخوانی
نیز استفاده کنید . اشیای فراخوانی کلاس های PHP ساده ای هستند که حاوی
__invoke
متد زیر هستند:
$schedule->call(new DeleteRecentUsers)->daily();
زمانبندی دستورات صنعتگر
علاوه بر زمانبندی تماسهای بسته، میتوانید
دستورات Artisan
و دستورات سیستم عامل را نیز برنامهریزی کنید. برای مثال، میتوانید از این
command
روش برای زمانبندی دستور Artisan با استفاده از نام یا کلاس دستور استفاده کنید:
$schedule->command('emails:send Taylor --force')->daily(); $schedule->command(EmailsCommand::class, ['Taylor', '--force'])->daily();
زمان بندی مشاغل در صف
این
job
روش ممکن است برای برنامه ریزی یک
کار در صف
استفاده شود . این روش روشی مناسب برای زمانبندی کارها بدون استفاده از
call
روش ایجاد بستههای دستی برای صفبندی کار ارائه میکند:
$schedule->job(new Heartbeat)->everyFiveMinutes(); // Dispatch the job to the "heartbeats" queue...$schedule->job(new Heartbeat, 'heartbeats')->everyFiveMinutes();
زمان بندی دستورات شل
این
exec
روش ممکن است برای صدور فرمان به سیستم عامل استفاده شود:
$schedule->exec('node /home/forge/script.js')->daily();
گزینه های فرکانس را برنامه ریزی کنید
زمانبندیهای مختلفی وجود دارد که میتوانید به وظایف خود اختصاص دهید:
روش | شرح |
---|---|
->cron('* * * * *'); |
وظیفه را بر روی یک برنامه Cron سفارشی اجرا کنید |
->everyMinute(); |
هر دقیقه کار را اجرا کنید |
->everyFiveMinutes(); |
این کار را هر پنج دقیقه یکبار اجرا کنید |
->everyTenMinutes(); |
این کار را هر ده دقیقه اجرا کنید |
->everyFifteenMinutes(); |
کار را هر پانزده دقیقه اجرا کنید |
->everyThirtyMinutes(); |
کار را هر سی دقیقه یکبار اجرا کنید |
->hourly(); |
هر ساعت کار را اجرا کنید |
->hourlyAt(17); |
این کار را هر ساعت 17 دقیقه قبل از ساعت اجرا کنید |
->daily(); |
کار را هر روز در نیمه شب اجرا کنید |
->dailyAt('13:00'); |
کار را هر روز ساعت 13:00 اجرا کنید |
->twiceDaily(1, 13); |
کار را هر روز در ساعت 1:00 و 13:00 اجرا کنید |
->weekly(); |
این کار را هر یکشنبه ساعت 00:00 انجام دهید |
->weeklyOn(1, '8:00'); |
کار را هر هفته دوشنبه ساعت 8:00 اجرا کنید |
->monthly(); |
کار را در روز اول هر ماه ساعت 00:00 اجرا کنید |
->monthlyOn(4, '15:00'); |
کار را هر ماه در تاریخ 4 ساعت 15:00 اجرا کنید |
->quarterly(); |
کار را در روز اول هر سه ماهه ساعت 00:00 اجرا کنید |
->yearly(); |
کار را در اولین روز هر سال ساعت 00: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(); |
کار را به شنبه محدود کنید |
->between($start, $end); |
کار را بین زمان شروع و پایان محدود کنید |
->when(Closure); |
کار را بر اساس آزمون حقیقت محدود کنید |
->environments($env); |
کار را به محیط های خاص محدود کنید |
بین محدودیت های زمانی
این
between
روش ممکن است برای محدود کردن اجرای یک کار بر اساس زمان روز استفاده شود:
$schedule->command('reminders:send') ->hourly() ->between('7:00', '22:00');
به طور مشابه، این
unlessBetween
روش می تواند برای حذف اجرای یک کار برای یک دوره زمانی استفاده شود:
$schedule->command('reminders:send') ->hourly() ->unlessBetween('23:00', '4:00');
محدودیت های آزمون حقیقت
این
when
روش ممکن است برای محدود کردن اجرای یک کار بر اساس نتیجه یک آزمون صدق داده شده استفاده شود. به عبارت دیگر، اگر داده داده شده
Closure
برگردد
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
روش ممکن است برای اجرای وظایف فقط در محیط های داده شده استفاده شود:
$schedule->command('emails:send') ->daily() ->environments(['staging', 'production']);
محدوده های زمانی
با استفاده از
timezone
روش، می توانید تعیین کنید که زمان یک کار برنامه ریزی شده باید در یک منطقه زمانی معین تفسیر شود:
$schedule->command('report:generate') ->timezone('America/New_York') ->at('02:00')
اگر منطقه زمانی یکسانی را به همه کارهای برنامه ریزی شده خود اختصاص می دهید، ممکن است بخواهید
scheduleTimezone
روشی را در
app/Console/Kernel.php
فایل خود تعریف کنید. این روش باید منطقه زمانی پیشفرض را که باید به همه وظایف زمانبندی شده اختصاص داده شود، برگرداند:
/** * 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);
اجرای وظایف روی یک سرور
برای استفاده از این ویژگی، برنامه شما باید از
memcached
یاredis
درایور کش به عنوان درایور کش پیش فرض برنامه شما استفاده کند. علاوه بر این، همه سرورها باید با یک سرور حافظه مرکزی یکسان در ارتباط باشند.
اگر برنامه شما بر روی چندین سرور اجرا می شود، می توانید یک کار برنامه ریزی شده را به اجرای تنها بر روی یک سرور محدود کنید. به عنوان مثال، فرض کنید یک کار برنامه ریزی شده دارید که هر جمعه شب یک گزارش جدید تولید می کند. اگر زمانبندی کار روی سه سرور کارگر اجرا شود، وظیفه برنامهریزیشده روی هر سه سرور اجرا میشود و گزارش را سه بار تولید میکند. خوب نیست!
برای نشان دادن اینکه وظیفه باید فقط روی یک سرور اجرا شود،
onOneServer
هنگام تعریف کار زمانبندی شده از روش استفاده کنید. اولین سروری که این وظیفه را به دست می آورد، یک قفل اتمی روی کار ایمن می کند تا از اجرای همزمان همان کار توسط سایر سرورها جلوگیری کند:
$schedule->command('report:generate') ->fridays() ->at('17:00') ->onOneServer();
وظایف پس زمینه
بهطور پیشفرض، چندین دستور برنامهریزیشده به طور همزمان بهطور متوالی اجرا میشوند. اگر فرمانهای طولانیمدت دارید، ممکن است دستورات بعدی خیلی دیرتر از زمان مورد انتظار شروع شود. اگر می خواهید دستورات را در پس زمینه اجرا کنید تا همه آنها به طور همزمان اجرا شوند، می توانید از
runInBackground
روش زیر استفاده کنید:
$schedule->command('analytics:report') ->daily() ->runInBackground();
این
runInBackground
روش فقط میتواند هنگام زمانبندی کارها از طریق متدهایcommand
و استفاده شودexec
.
حالت تعمیر و نگهداری
کارهای برنامه ریزی شده لاراول زمانی که لاراول در
حالت تعمیر و نگهداری
است اجرا نمی شوند ، زیرا ما نمی خواهیم وظایف شما با تعمیرات ناتمام که ممکن است در سرور خود انجام می دهید تداخل داشته باشد. با این حال، اگر می خواهید یک کار را مجبور کنید حتی در حالت تعمیر و نگهداری اجرا شود، می توانید از
evenInMaintenanceMode
روش زیر استفاده کنید:
$schedule->command('emails:send')->evenInMaintenanceMode();
خروجی وظیفه
زمانبند لاراول چندین روش راحت را برای کار با خروجی تولید شده توسط وظایف برنامه ریزی شده ارائه می دهد. ابتدا، با استفاده از
sendOutputTo
روش، می توانید خروجی را برای بررسی بعدی به یک فایل ارسال کنید:
$schedule->command('emails:send') ->daily() ->sendOutputTo($filePath);
اگر می خواهید خروجی را به یک فایل معین اضافه کنید، می توانید از
appendOutputTo
روش زیر استفاده کنید:
$schedule->command('emails:send') ->daily() ->appendOutputTo($filePath);
با استفاده از این
emailOutputTo
روش، می توانید خروجی را به آدرس ایمیل دلخواه خود ایمیل کنید. قبل از ارسال ایمیل خروجی یک کار، باید
سرویس های ایمیل
لاراول را پیکربندی کنید :
$schedule->command('foo') ->daily() ->sendOutputTo($filePath) ->emailOutputTo('foo@example.com');
اگر فقط می خواهید خروجی را ایمیل کنید در صورت شکست دستور، از
emailOutputOnFailure
روش زیر استفاده کنید:
$schedule->command('foo') ->daily() ->emailOutputOnFailure('foo@example.com');
روش های
emailOutputTo
,emailOutputOnFailure
,sendOutputTo
, وappendOutputTo
منحصر به روشcommand
و هستندexec
.
قلاب های وظیفه
با استفاده از
before
و
after
متدها، می توانید کدی را مشخص کنید که قبل و بعد از اتمام کار برنامه ریزی شده اجرا شود:
$schedule->command('emails:send') ->daily() ->before(function () { // Task is about to start... }) ->after(function () { // Task is complete... });
متدها
onSuccess
و
onFailure
به شما اجازه می دهند کدی را مشخص کنید که در صورت موفقیت یا شکست کار برنامه ریزی شده اجرا شود:
$schedule->command('emails:send') ->daily() ->onSuccess(function () { // The task succeeded... }) ->onFailure(function () { // The task failed... });
پینگ کردن URL ها
با استفاده از
pingBefore
و
thenPing
، زمانبندیکننده میتواند بهطور خودکار یک URL داده شده را قبل یا بعد از تکمیل یک کار پینگ کند. این روش برای اطلاع رسانی به یک سرویس خارجی مانند
Laravel 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
$schedule->command('emails:send') ->daily() ->pingOnSuccess($successUrl) ->pingOnFailure($failureUrl);
همه روشهای پینگ به کتابخانه HTTP Guzzle نیاز دارند. با استفاده از مدیریت بسته Composer می توانید Guzzle را به پروژه خود اضافه کنید:
composer require guzzlehttp/guzzle