• Introducere
    • Definirea programărilor
      • Comandă Artisan de programare
      • Programarea lucrărilor în coadă
      • Comandă Shell de programare
      • Opțiuni de frecvență a programării
      • Funcții orare
      • Prevenirea suprapunerilor de sarcini
    • .

    • Executarea sarcinilor pe un server
    • Tachete de fundal
    • Modul de întreținere
  • Executarea planificatorului
    • Executarea planificatorului la nivel local
  • Task Output
  • Task Hooks

Introducere

În trecut, este posibil să fi scris o intrare de configurare cron pentru fiecare sarcină pe care trebuia să o programați pe serverul dumneavoastră. Cu toate acestea, acest lucru poate deveni rapid o pacoste, deoarece programarea sarcinilor nu mai este în controlul sursei și trebuie să intrați prin SSH în serverul dumneavoastră pentru a vizualiza intrările cron existente sau pentru a adăuga intrări suplimentare.

Programatorul de comenzi al lui Laravel oferă o abordare nouă pentru gestionarea sarcinilor programate pe serverul dumneavoastră. Planificatorul vă permite să vă definiți fluent și expresiv programul de comenzi în cadrul aplicației Laravel în sine. Atunci când folosiți planificatorul, este nevoie de o singură intrare cron pe serverul dvs. Programarea sarcinii dvs. este definită în metoda schedule a fișierului app/Console/Kernel.php. Pentru a vă ajuta să începeți, un exemplu simplu este definit în cadrul metodei.

Definirea programărilor

Puteți defini toate sarcinile programate în metoda schedule a clasei App\Console\Kernel a aplicației dvs. Pentru a începe, să ne uităm la un exemplu. În acest exemplu, vom programa o închidere care să fie apelată în fiecare zi la miezul nopții. În cadrul închiderii, vom executa o interogare a bazei de date pentru a șterge un tabel:

<?phpnamespace 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(); }}

În plus față de programarea cu ajutorul închiderilor, puteți programa și obiecte invocabile. Obiectele invocabile sunt clase PHP simple care conțin o metodă __invoke:

$schedule->call(new DeleteRecentUsers)->daily();

Dacă doriți să vizualizați o imagine de ansamblu a sarcinilor programate și următoarea dată când vor fi programate să se execute, puteți utiliza comanda schedule:list Artisan:

php artisan schedule:list

Scheduling Artisan Commands

În plus față de programarea închiderilor, puteți programa și comenzi Artisan și comenzi de sistem. De exemplu, puteți utiliza metoda command pentru a programa o comandă Artisan utilizând fie numele comenzii, fie clasa acesteia.

Când programați comenzi Artisan utilizând numele clasei comenzii, puteți trece o matrice de argumente suplimentare la linia de comandă care trebuie furnizate comenzii atunci când este invocată:

use App\Console\Commands\SendEmailsCommand;$schedule->command('emails:send Taylor --force')->daily();$schedule->command(SendEmailsCommand::class, )->daily();

Scheduling Queued Jobs

Metoda job poate fi utilizată pentru a programa o comandă în coadă. Această metodă oferă o modalitate convenabilă de programare a lucrărilor aflate în coadă fără a utiliza metoda call pentru a defini închiderile pentru a pune în coadă lucrarea:

use App\Jobs\Heartbeat;$schedule->job(new Heartbeat)->everyFiveMinutes();

Se pot furniza al doilea și al treilea argument opțional metodei job care specifică numele cozii și conexiunea cozii care trebuie utilizate pentru a pune în coadă lucrarea:

use App\Jobs\Heartbeat;// Dispatch the job to the "heartbeats" queue on the "sqs" connection...$schedule->job(new Heartbeat, 'heartbeats', 'sqs')->everyFiveMinutes();

Programarea comenzilor Shell

Metoda exec poate fi utilizată pentru a emite o comandă către sistemul de operare:

$schedule->exec('node /home/forge/script.js')->daily();

Opțiuni privind frecvența de programare

Am văzut deja câteva exemple despre cum puteți configura o sarcină pentru a se executa la intervale specificate. Cu toate acestea, există mult mai multe frecvențe de programare a sarcinilor pe care le puteți atribui unei sarcini:

.

.

.

.

.

Metoda Descriere
->cron('* * * * *'); Executați sarcina pe un program cron personalizat
->everyMinute(); Executați sarcina la fiecare minut
->everyTwoMinutes(); Executați sarcina la fiecare două minute
->everyThreeMinutes(); Executați sarcina la fiecare trei minute
->everyFourMinutes(); Executați sarcina la fiecare patru minute
->everyFiveMinutes(); Executați sarcina la fiecare cinci minute
->everyTenMinutes(); Executați sarcina la fiecare zece minute
->everyFifteenMinutes(); Executați sarcina la fiecare cincisprezece minute
->everyThirtyMinutes(); Executați sarcina la fiecare treizeci de minute
->hourly(); Executați sarcina la fiecare oră
->hourlyAt(17); Executați sarcina în fiecare oră la 17 minute după ora
->everyTwoHours(); Executați sarcina la fiecare două ore
->everyThreeHours(); Rulați sarcina la fiecare trei ore
->everyFourHours(); Rulați sarcina la fiecare patru ore
->everySixHours(); Rulați sarcina la fiecare șase ore
->daily(); Executați sarcina în fiecare zi la miezul nopții
->dailyAt('13:00'); Executați sarcina în fiecare zi la ora 13:00
->twiceDaily(1, 13); Executați sarcina în fiecare zi la ora 1:00 & 13:00
->weekly(); Executați sarcina în fiecare duminică la ora 00:00
->weeklyOn(1, '8:00'); Executați sarcina în fiecare săptămână, luni, la ora 8:00
->monthly(); Executați sarcina în prima zi a fiecărei luni, la ora 00:00
->monthlyOn(4, '15:00'); Executați sarcina în fiecare lună pe data de 4 la ora 15:00
->twiceMonthly(1, 16, '13:00'); Executați sarcina lunar pe 1 și 16 la ora 13:00
->lastDayOfMonth('15:00'); Executați sarcina în ultima zi a lunii la ora 15:00
->quarterly(); Executați sarcina în prima zi a fiecărui trimestru la ora 00:00
->yearly(); Executați sarcina în prima zi a fiecărui an la ora 00:00
->yearlyOn(6, 1, '17:00'); Executați sarcina în fiecare an la 1 iunie la ora 17:00
->timezone('America/New_York'); Setați fusul orar pentru sarcină

Aceste metode pot fi combinate cu constrângeri suplimentare pentru a crea programe și mai bine puse la punct, care se execută numai în anumite zile ale săptămânii. De exemplu, puteți programa o comandă să se execute săptămânal în ziua de luni:

// 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');

O listă de constrângeri suplimentare de programare poate fi găsită mai jos:

.

.

.

.

Metoda Descriere
->weekdays(); Limitați sarcina la zilele lucrătoare
->weekends(); Limitați sarcina la sfârșit de săptămână
->sundays(); Limitați sarcina la duminică
->mondays(); Limitați sarcina pentru luni
->tuesdays(); Limitați sarcina pentru marți
->wednesdays(); Limitați sarcina până miercuri
->thursdays(); Limitați sarcina până joi
->fridays(); Limitați sarcina până vineri
->saturdays(); Limitați sarcina la sâmbătă
->days(array|mixed); Limitați sarcina la anumite zile
->between($startTime, $endTime); Limitați sarcina să se execute între orele de început și de sfârșit
->unlessBetween($startTime, $endTime); Limitați sarcina să nu se execute între orele de început și de sfârșit Limitați sarcina să nu se execute între orele de început și de orele de sfârșit
->when(Closure); Limitați sarcina pe baza unui test de veridicitate
->environments($env); Limitați sarcina la orele specifice de medii

Day Constraints

Metoda days poate fi utilizată pentru a limita executarea unei sarcini la anumite zile ale săptămânii. De exemplu, puteți programa o comandă pentru a se executa din oră în oră în zilele de duminică și miercuri:

$schedule->command('emails:send') ->hourly() ->days();

Alternativ, puteți utiliza constantele disponibile în clasa Illuminate\Console\Scheduling\Schedule atunci când definiți zilele în care o sarcină ar trebui să se execute:

use Illuminate\Console\Scheduling\Schedule;$schedule->command('emails:send') ->hourly() ->days();

Between Time Constraints

Metoda between poate fi utilizată pentru a limita executarea unei sarcini în funcție de ora din zi:

$schedule->command('emails:send') ->hourly() ->between('7:00', '22:00');

În mod similar, metoda unlessBetween poate fi utilizată pentru a exclude executarea unei sarcini pentru o perioadă de timp:

$schedule->command('emails:send') ->hourly() ->unlessBetween('23:00', '4:00');

Constrângeri de test de adevăr

Metoda when poate fi utilizată pentru a limita executarea unei sarcini pe baza rezultatului unui anumit test de adevăr. Cu alte cuvinte, dacă închiderea dată returnează true, sarcina se va executa atâta timp cât nici o altă condiție restrictivă nu o împiedică să se execute:

$schedule->command('emails:send')->daily()->when(function () { return true;});

Metoda skip poate fi văzută ca inversul lui when. Dacă metoda skip returnează true, sarcina programată nu va fi executată:

$schedule->command('emails:send')->daily()->skip(function () { return true;});

Când se utilizează metode when înlănțuite, comanda programată se va executa numai dacă toate condițiile when returnează true.

Constrângeri de mediu

Metoda environments poate fi utilizată pentru a executa sarcini numai în mediile date (așa cum sunt definite de variabila de mediu APP_ENV):

$schedule->command('emails:send') ->daily() ->environments();

Fuze orare

Utilizând metoda timezone, puteți specifica faptul că ora unei sarcini programate trebuie interpretată într-un anumit fus orar:

$schedule->command('report:generate') ->timezone('America/New_York') ->at('2:00')

Dacă atribuiți în mod repetat același fus orar tuturor sarcinilor programate, este posibil să doriți să definiți o metodă scheduleTimezone în clasa App\Console\Kernel. Această metodă ar trebui să returneze fusul orar implicit care ar trebui să fie atribuit tuturor sarcinilor programate:

/** * Get the timezone that should be used by default for scheduled events. * * @return \DateTimeZone|string|null */protected function scheduleTimezone(){ return 'America/Chicago';}

{note} Nu uitați că unele fusuri orare utilizează ora de vară. Atunci când au loc modificări ale orei de vară, este posibil ca sarcina dumneavoastră programată să se execute de două ori sau chiar să nu se execute deloc. Din acest motiv, vă recomandăm să evitați programarea în funcție de fusul orar atunci când este posibil.

Prevenirea suprapunerilor de sarcini

În mod implicit, sarcinile programate vor fi executate chiar dacă instanța anterioară a sarcinii este încă în execuție. Pentru a preveni acest lucru, puteți utiliza metoda withoutOverlapping:

$schedule->command('emails:send')->withoutOverlapping();

În acest exemplu, comanda emails:send Artisan va fi rulată la fiecare minut, dacă nu este deja în curs de execuție. Metoda withoutOverlapping este utilă în special dacă aveți sarcini care variază drastic în timpul de execuție, împiedicându-vă să preziceți exact cât timp va dura o anumită sarcină.

Dacă este necesar, puteți specifica câte minute trebuie să treacă înainte ca blocajul „fără suprapunere” să expire. În mod implicit, blocarea va expira după 24 de ore:

$schedule->command('emails:send')->withoutOverlapping(10);

Executarea sarcinilor pe un singur server

{note} Pentru a utiliza această caracteristică, aplicația dvs. trebuie să utilizeze driverul de cache database, memcached, dynamodb sau redis ca driver de cache implicit al aplicației dvs. În plus, toate serverele trebuie să comunice cu același server cache central.

Dacă programatorul aplicației dvs. rulează pe mai multe servere, puteți limita o sarcină programată pentru a se executa numai pe un singur server. De exemplu, să presupunem că aveți o sarcină programată care generează un nou raport în fiecare vineri seara. Dacă planificatorul de sarcini rulează pe trei servere de lucru, sarcina programată se va executa pe toate cele trei servere și va genera raportul de trei ori. Nu este bine!

Pentru a indica faptul că sarcina trebuie să ruleze pe un singur server, utilizați metoda onOneServer atunci când definiți sarcina programată. Primul server care obține sarcina va asigura un blocaj atomic asupra sarcinii pentru a împiedica alte servere să ruleze aceeași sarcină în același timp:

$schedule->command('report:generate') ->fridays() ->at('17:00') ->onOneServer();

Tachete de fundal

În mod implicit, mai multe sarcini programate în același timp se vor executa secvențial, pe baza ordinii în care sunt definite în metoda schedule. Dacă aveți sarcini care se execută de mult timp, acest lucru poate face ca sarcinile ulterioare să înceapă mult mai târziu decât se anticipa. Dacă doriți să executați sarcini în fundal, astfel încât toate să se execute simultan, puteți utiliza metoda runInBackground:

$schedule->command('analytics:report') ->daily() ->runInBackground();

{note} Metoda poate fi utilizată numai atunci când se programează sarcini prin intermediul metodelor command și exec.

Modul de întreținere

Tașelele programate ale aplicației dvs. nu vor rula atunci când aplicația se află în modul de întreținere, deoarece nu dorim ca sarcinile dvs. să interfereze cu orice operațiune de întreținere neterminată pe care o puteți efectua pe serverul dvs. Cu toate acestea, dacă doriți să forțați o sarcină să ruleze chiar și în modul de întreținere, puteți apela metoda evenInMaintenanceMode atunci când definiți sarcina:

$schedule->command('emails:send')->evenInMaintenanceMode();

Running The Scheduler

Acum că am învățat cum să definim sarcinile programate, haideți să discutăm cum să le rulăm efectiv pe serverul nostru. Comanda schedule:run Artisan va evalua toate sarcinile programate și va determina dacă acestea trebuie să ruleze în funcție de ora curentă a serverului.

Așa că, atunci când folosim planificatorul Laravel, trebuie doar să adăugăm o singură intrare de configurare cron pe serverul nostru care să ruleze comanda schedule:run la fiecare minut. Dacă nu știți cum să adăugați intrări cron pe serverul dumneavoastră, luați în considerare utilizarea unui serviciu precum Laravel Forge, care poate gestiona intrările cron pentru dumneavoastră:

* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1

Executarea planificatorului la nivel local

În mod normal, nu veți adăuga o intrare cron a planificatorului pe mașina dumneavoastră de dezvoltare locală. În schimb, puteți utiliza comanda schedule:work Artisan. Această comandă va rula în prim-plan și va invoca planificatorul la fiecare minut până când veți încheia comanda:

php artisan schedule:work

Task Output

Calculatorul Laravel oferă mai multe metode convenabile pentru a lucra cu rezultatul generat de sarcinile planificate. În primul rând, utilizând metoda sendOutputTo, puteți trimite ieșirea într-un fișier pentru o inspecție ulterioară:

$schedule->command('emails:send') ->daily() ->sendOutputTo($filePath);

Dacă doriți să adăugați ieșirea la un anumit fișier, puteți utiliza metoda appendOutputTo:

$schedule->command('emails:send') ->daily() ->appendOutputTo($filePath);

Utilizând metoda emailOutputTo, puteți trimite ieșirea prin e-mail la o adresă de e-mail la alegere. Înainte de a trimite prin e-mail ieșirea unei sarcini, trebuie să configurați serviciile de e-mail ale Laravel:

$schedule->command('report:generate') ->daily() ->sendOutputTo($filePath) ->emailOutputTo('');

Dacă doriți să trimiteți prin e-mail ieșirea doar dacă comanda Artisan sau de sistem programată se termină cu un cod de ieșire diferit de zero, utilizați metoda emailOutputOnFailure:

$schedule->command('report:generate') ->daily() ->emailOutputOnFailure('');

{note} Metodele emailOutputTo, emailOutputOnFailure, sendOutputTo și appendOutputTo sunt exclusive față de metodele command și exec.

Task Hooks

Utilizând metodele before și after, puteți specifica codul care urmează să fie executat înainte și după ce sarcina programată este executată:

$schedule->command('emails:send') ->daily() ->before(function () { // The task is about to execute... }) ->after(function () { // The task has executed... });

Metodele onSuccess și onFailure vă permit să specificați codul care urmează să fie executat dacă sarcina programată reușește sau eșuează. Un eșec indică faptul că comanda Artisan sau de sistem programată s-a încheiat cu un cod de ieșire diferit de zero:

$schedule->command('emails:send') ->daily() ->onSuccess(function () { // The task succeeded... }) ->onFailure(function () { // The task failed... });

Dacă ieșirea este disponibilă de la comanda dumneavoastră, o puteți accesa în cârligele after, onSuccess sau onFailure prin indicarea de tip a unei instanțe Illuminate\Support\Stringable ca argument $output al definiției de închidere a cârligului dumneavoastră:

use Illuminate\Support\Stringable;$schedule->command('emails:send') ->daily() ->onSuccess(function (Stringable $output) { // The task succeeded... }) ->onFailure(function (Stringable $output) { // The task failed... });

Pingând URL-uri

Utilizând metodele pingBefore și thenPing, planificatorul poate ping automat un anumit URL înainte sau după ce o sarcină este executată. Această metodă este utilă pentru a notifica un serviciu extern, cum ar fi Envoyer, că sarcina programată începe sau a terminat execuția:

$schedule->command('emails:send') ->daily() ->pingBefore($url) ->thenPing($url);

Metodele pingBeforeIf și thenPingIf pot fi utilizate pentru a trimite un ping la o anumită adresă URL numai dacă o anumită condiție este true:

$schedule->command('emails:send') ->daily() ->pingBeforeIf($condition, $url) ->thenPingIf($condition, $url);

Metodele pingOnSuccess și pingOnFailure pot fi utilizate pentru a trimite un ping la o anumită adresă URL numai dacă sarcina reușește sau eșuează. Un eșec indică faptul că Artisan programat sau comanda de sistem s-a încheiat cu un cod de ieșire diferit de zero:

$schedule->command('emails:send') ->daily() ->pingOnSuccess($successUrl) ->pingOnFailure($failureUrl);

Toate metodele ping necesită biblioteca Guzzle HTTP. Guzzle este de obicei instalat în mod implicit în toate proiectele Laravel noi, dar, puteți instala manual Guzzle în proiectul dvs. folosind managerul de pachete Composer dacă a fost eliminat din greșeală:

composer require guzzlehttp/guzzle