• Úvod
  • Definice plánů
    • Příkazy Artisan pro plánování
    • Příkazy pro plánování úloh ve frontě
    • Příkazy shellu pro plánování
    • Volby frekvence plánování
    • Časové zóny
    • Předcházení překrývání úloh
    • .

    • Spouštění úloh na jednom serveru
    • Úlohy na pozadí
    • Režim údržby
  • Spouštění plánovače
    • Spouštění plánovače lokálně
  • Výstupy úloh
  • Háčky úloh

Úvod

V minulosti, jste možná pro každou úlohu, kterou jste potřebovali naplánovat na serveru, napsali konfigurační položku cronu. To se však může rychle stát otravným, protože plán úloh již není ve zdrojovém kódu a musíte se SSH připojit k serveru, abyste mohli zobrazit existující položky cronu nebo přidat další položky.

Plánovač příkazů Laravel nabízí nový přístup ke správě naplánovaných úloh na serveru. Plánovač umožňuje plynule a expresivně definovat plán příkazů v rámci samotné aplikace Laravel. Při použití plánovače je na serveru potřeba pouze jedna položka cronu. Váš plán úloh je definován v metodě schedule souboru app/Console/Kernel.php. Abyste mohli začít, je v rámci metody definován jednoduchý příklad.

Definování rozvrhu

V metodě schedule třídy App\Console\Kernel vaší aplikace můžete definovat všechny své naplánované úlohy. Pro začátek se podívejme na příklad. V tomto příkladu naplánujeme uzávěrku, která se bude volat každý den o půlnoci. V rámci uzávěrky provedeme databázový dotaz, který vymaže tabulku:

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

Kromě plánování pomocí uzávěrek můžete plánovat také volatelné objekty. Vyvolatelné objekty jsou jednoduché třídy jazyka PHP, které obsahují metodu __invoke:

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

Pokud chcete zobrazit přehled naplánovaných úloh a jejich příští spuštění, můžete použít příkaz schedule:list Artisan:

php artisan schedule:list

Plánování příkazů Artisan

Kromě plánování uzávěrek můžete také plánovat příkazy Artisan a systémové příkazy. Například metodou command můžete naplánovat příkaz Artisan pomocí názvu nebo třídy příkazu.

Při plánování příkazů Artisan pomocí názvu třídy příkazu můžete předat pole dalších argumentů příkazového řádku, které mají být příkazu poskytnuty při jeho vyvolání:

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

Plánování úloh ve frontě

Metodu job lze použít k plánování úlohy ve frontě. Tato metoda poskytuje pohodlný způsob plánování úloh ve frontě bez použití metody call pro definování uzávěrek pro zařazení úlohy do fronty:

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

Možno zadat volitelný druhý a třetí argument metody job, který určuje název fronty a připojení fronty, která má být použita pro zařazení úlohy do fronty:

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

Příkazy shellu

Metodu exec lze použít k zadání příkazu operačnímu systému:

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

Volby frekvence plánování

Už jsme viděli několik příkladů, jak lze nastavit spouštění úlohy v určených intervalech. Existuje však mnohem více frekvencí plánování úloh, které můžete úloze přiřadit:

.

.

Metoda Popis
->cron('* * * * *'); Spustit úlohu podle vlastního plánu cron
->everyMinute(); Spustit úlohu každou minutu
->everyTwoMinutes(); Spustit úlohu každé dvě minuty
->everyThreeMinutes(); Spustit úlohu každé tři minuty
->everyFourMinutes(); Spustit úlohu každé čtyři minuty
->everyFiveMinutes(); Spustit úlohu každých pět minut
->everyTenMinutes(); Spustit úlohu každých deset minut
->everyFifteenMinutes(); Spustit úlohu každých patnáct minut
->everyThirtyMinutes(); Spustit úlohu každých třicet minut
->hourly(); Spustit úlohu každou hodinu
->hourlyAt(17); Spustit úlohu každou hodinu v 17 minut po hodině
->everyTwoHours(); Spustit úlohu každé dvě hodiny
->everyThreeHours(); Spustit úlohu každé tři hodiny
->everyFourHours(); Spustit úlohu každé čtyři hodiny
->everySixHours(); Spustit úlohu každých šest hodin
->daily(); Spustit úlohu každý den o půlnoci
->dailyAt('13:00'); Spustit úlohu každý den ve 13 hodin:00
->twiceDaily(1, 13); Spustit úlohu denně v 1:00 & 13:00
->weekly(); Spustit úlohu každou neděli v 00 hod:00
->weeklyOn(1, '8:00'); Spustit úlohu každý týden v pondělí v 8:00
->monthly(); Spustit úlohu každý první den v měsíci v 00:00:00
->monthlyOn(4, '15:00'); Spustit úlohu každý měsíc 4. den v 15:00
->twiceMonthly(1, 16, '13:00'); Spustit úlohu každý měsíc 1. a 16. den ve 13:00:00
->lastDayOfMonth('15:00'); Spustit úlohu poslední den v měsíci v 15 hod:00
->quarterly(); Spustit úlohu první den každého čtvrtletí v 00 hod:00
->yearly(); Spustit úlohu první den každého roku v 00:00
->yearlyOn(6, 1, '17:00'); Spustit úlohu každý rok 1. června v 17:00:00
->timezone('America/New_York'); Nastavte časové pásmo pro úlohu

Tyto metody lze kombinovat s dalšími omezeními a vytvořit tak ještě jemněji vyladěné plány, které se spouštějí pouze v určité dny v týdnu. Například můžete naplánovat příkaz tak, aby se spouštěl každý týden v pondělí:

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

Seznam dalších omezení plánu naleznete níže:

.

.

Metoda Popis
->weekdays(); Omezit úlohu na pracovní dny
->weekends(); Omezit úlohu na víkendy
->sundays(); Omezit úlohu na neděli
->mondays(); Omezit úkol na pondělí
->tuesdays(); Omezit úkol na úterý
->wednesdays(); Omezit úkol. na středu
->thursdays(); Omezit úkol na čtvrtek
->fridays(); Omezit úkol na pátek
->saturdays(); Omezit úkol na sobotu
->days(array|mixed); Omezit úkol na konkrétní dny
->between($startTime, $endTime); Omezit spuštění úlohy mezi časem zahájení a ukončením
->unlessBetween($startTime, $endTime); Omezit, aby úloha nebyla spuštěna mezi časem zahájení a ukončením
->unlessBetween($startTime, $endTime); Omezit, aby úloha nebyla spuštěna mezi časem zahájení a koncovým časem
->when(Closure); Omezit úlohu na základě testu pravdivosti
->environments($env); Omezit úlohu na konkrétní prostředí

Omezení na dny

Metodu days lze použít k omezení provádění úlohy na konkrétní dny v týdnu. Například můžete naplánovat, aby se příkaz spouštěl každou hodinu v neděli a ve středu:

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

Případně můžete při definování dnů, ve kterých se má úloha spustit, použít konstanty dostupné ve třídě Illuminate\Console\Scheduling\Schedule:

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

Omezení mezi časy

Metodu between lze použít k omezení provádění úlohy na základě denní doby:

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

Podobně lze metodu unlessBetween použít k vyloučení provádění úlohy po určitou dobu:

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

Omezení pravdivostního testu

Metodu when lze použít k omezení provádění úlohy na základě výsledku daného pravdivostního testu. Jinými slovy, pokud daný uzávěr vrátí true, úloha se provede, pokud jejímu provedení nebrání žádné jiné omezující podmínky:

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

Metodu skip lze považovat za inverzní k when. Pokud metoda skip vrátí true, naplánovaná úloha se neprovede:

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

Při použití zřetězených metod when se naplánovaný příkaz provede pouze tehdy, pokud všechny podmínky when vrátí true.

Omezení prostředí

Metodu environments lze použít k provádění úloh pouze v daných prostředích (definovaných proměnnou prostředí APP_ENV):

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

Časové pásmo

Pomocí metody timezone můžete určit, že čas naplánované úlohy má být interpretován v daném časovém pásmu:

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

Pokud opakovaně přiřazujete všem naplánovaným úlohám stejné časové pásmo, můžete ve své třídě App\Console\Kernel definovat metodu scheduleTimezone. Tato metoda by měla vracet výchozí časové pásmo, které by mělo být přiřazeno všem naplánovaným úlohám:

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

{poznámka} Nezapomeňte, že některá časová pásma využívají letní čas. Když dojde ke změně letního času, naplánovaná úloha se může spustit dvakrát nebo se dokonce nespustí vůbec. Z tohoto důvodu doporučujeme vyhnout se plánování podle časových pásem, pokud je to možné.

Předcházení překrývání úloh

Ve výchozím nastavení se naplánované úlohy spustí, i když je předchozí instance úlohy stále spuštěna. Chcete-li tomu zabránit, můžete použít metodu withoutOverlapping:

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

V tomto příkladu bude příkaz emails:send Artisan spuštěn každou minutu, pokud ještě není spuštěn. Metoda withoutOverlapping je užitečná zejména v případě, že máte úlohy, jejichž doba provádění se drasticky liší, což vám brání přesně předpovědět, jak dlouho bude daná úloha trvat.

Pokud je to nutné, můžete určit, kolik minut musí uplynout, než vyprší zámek „bez překrývání“. Ve výchozím nastavení zámek vyprší po 24 hodinách:

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

Spouštění úloh na jednom serveru

{poznámka} Chcete-li tuto funkci využívat, musí vaše aplikace používat jako výchozí ovladač mezipaměti database, memcached, dynamodb nebo redis. Kromě toho musí všechny servery komunikovat se stejným centrálním serverem mezipaměti.

Pokud plánovač vaší aplikace běží na více serverech, můžete naplánovanou úlohu omezit tak, aby se provedla pouze na jednom serveru. Předpokládejme například, že máte naplánovanou úlohu, která každý pátek večer generuje novou zprávu. Pokud plánovač úloh běží na třech pracovních serverech, naplánovaná úloha se spustí na všech třech serverech a sestavu vygeneruje třikrát. To není dobré!“

Chcete-li uvést, že úloha má běžet pouze na jednom serveru, použijte při definování naplánované úlohy metodu onOneServer. První server, který úlohu získá, zajistí atomický zámek úlohy, aby zabránil spuštění stejné úlohy na jiných serverech ve stejnou dobu:

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

Úlohy na pozadí

Ve výchozím nastavení se více úloh naplánovaných ve stejnou dobu spustí postupně podle pořadí, v jakém jsou definovány v metodě schedule. Pokud máte dlouho běžící úlohy, může to způsobit, že se následující úlohy spustí mnohem později, než se předpokládalo. Pokud chcete spouštět úlohy na pozadí tak, aby mohly být spuštěny všechny současně, můžete použít metodu runInBackground:

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

{poznámka} Metodu runInBackground lze použít pouze při plánování úloh pomocí metod command a exec.

Režim údržby

Plánované úlohy vaší aplikace nebudou spuštěny, pokud je aplikace v režimu údržby, protože nechceme, aby vaše úlohy narušovaly nedokončenou údržbu, kterou na serveru případně provádíte. Pokud však chcete vynutit spuštění úlohy i v režimu údržby, můžete při definování úlohy zavolat metodu evenInMaintenanceMode:

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

Spuštění plánovače

Teď, když jsme se naučili definovat naplánované úlohy, probereme, jak je na našem serveru skutečně spustit. Příkaz schedule:run Artisan vyhodnotí všechny naplánované úlohy a určí, zda je třeba je spustit na základě aktuálního času serveru.

Při použití plánovače Laravel nám tedy stačí přidat na náš server jedinou položku konfigurace cronu, která každou minutu spustí příkaz schedule:run. Pokud nevíte, jak na server přidat položky cronu, zvažte použití služby, jako je Laravel Forge, která může položky cronu spravovat za vás:

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

Spouštění plánovače lokálně

Typicky byste položku cronu plánovače na lokální vývojový počítač nepřidávali. Místo toho můžete použít příkaz schedule:work Artisan. Tento příkaz se spustí v popředí a každou minutu vyvolá plánovač, dokud jej neukončíte:

php artisan schedule:work

Výstupy úloh

Plánovač Laravel poskytuje několik pohodlných metod pro práci s výstupy generovanými naplánovanými úlohami. Nejprve můžete pomocí metody sendOutputTo odeslat výstup do souboru pro pozdější kontrolu:

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

Pokud chcete výstup připojit k danému souboru, můžete použít metodu appendOutputTo:

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

Pomocí metody emailOutputTo můžete výstup odeslat e-mailem na vámi zvolenou e-mailovou adresu. Před odesláním výstupu úlohy e-mailem byste měli nakonfigurovat e-mailové služby Laravel:

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

Pokud chcete odeslat výstup e-mailem pouze v případě, že naplánovaný příkaz Artisan nebo systémový příkaz skončí s nenulovým výstupním kódem, použijte metodu emailOutputOnFailure:

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

{poznámka} Metody emailOutputTo, emailOutputOnFailure, sendOutputTo a appendOutputTo jsou výlučné pro metody command a exec.

Háčky úlohy

Pomocí metod before a after můžete určit kód, který se provede před a po provedení naplánované úlohy:

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

Metody onSuccess a onFailure umožňují určit kód, který se provede, pokud naplánovaná úloha uspěje nebo selže. Neúspěch znamená, že naplánovaný příkaz Artisan nebo systémový příkaz skončil s nenulovým výstupním kódem:

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

Je-li k dispozici výstup z příkazu, můžete k němu přistupovat v háčcích after, onSuccess nebo onFailure typovým označením instance Illuminate\Support\Stringable jako argumentu $output definice uzávěru háčku:

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

Pingování URL adres

Pomocí metod pingBefore a thenPing může plánovač automaticky pingovat danou URL adresu před nebo po provedení úlohy. Tato metoda je užitečná pro upozornění externí služby, jako je například Envoyer, že vaše naplánovaná úloha začíná nebo že její provádění skončilo:

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

Metody pingBeforeIf a thenPingIf lze použít k pingování dané adresy URL pouze v případě, že je splněna daná podmínka true:

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

Metody pingOnSuccess a pingOnFailure lze použít k pingování dané adresy URL pouze v případě, že úloha uspěje nebo selže. Neúspěch znamená, že naplánovaný příkaz Artisan nebo systémový příkaz skončil s nenulovým kódem ukončení:

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

Všechny metody ping vyžadují knihovnu Guzzle HTTP. Guzzle je obvykle standardně nainstalován do všech nových projektů Laravel, ale pokud byl omylem odstraněn, můžete jej do projektu nainstalovat ručně pomocí správce balíčků Composer:

composer require guzzlehttp/guzzle

.