نسخه:

برنامه ریزی وظایف

معرفی

در گذشته، ممکن است برای هر وظیفه ای که برای برنامه ریزی روی سرور خود نیاز داشتید، یک ورودی 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