• Inleiding
  • Roosters definiëren
    • Artisan-opdrachten
    • Roosteren van taken in wachtrij
    • Roosteren van Shell-opdrachten
    • Frequentieopties
    • Timezones
    • Voorkomen dat taken elkaar overlappen
    • Taken op één server uitvoeren
    • Taken op de achtergrond
    • Onderhoudsmodus
  • De scheduler uitvoeren
    • De scheduler lokaal uitvoeren
  • Taakuitvoer
  • Taakhaken

Inleiding

In het verleden, hebt u misschien een cron configuratie geschreven voor elke taak die u op uw server wilde plannen. Dit kan echter al snel een probleem worden omdat uw taak schema niet langer in source control is en u moet SSH in uw server om uw bestaande cron entries te bekijken of extra entries toe te voegen.

Laravel’s command scheduler biedt een nieuwe aanpak voor het beheren van geplande taken op uw server. De scheduler stelt u in staat om vloeiend en expressief uw commando schema te definiëren binnen uw Laravel applicatie zelf. Wanneer je de scheduler gebruikt is er slechts één cron entry nodig op je server. Je opdracht schema wordt gedefinieerd in de app/Console/Kernel.php file’s schedule method. Om je op weg te helpen, is een eenvoudig voorbeeld gedefinieerd in de methode.

Defining Schedules

Je kunt al je geplande taken definiëren in de schedule methode van de App\Console\Kernel klasse van je applicatie. Om te beginnen, laten we eens kijken naar een voorbeeld. In dit voorbeeld plannen we een afsluiting die elke dag om middernacht wordt aangeroepen. Binnen de closure voeren we een database query uit om een tabel leeg te maken:

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

Naast het gebruik van closures, kunt u ook invokable objecten gebruiken. Invokable objects zijn eenvoudige PHP-klassen die een __invoke-methode bevatten:

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

Als u een overzicht wilt zien van uw geplande taken en de volgende keer dat ze moeten worden uitgevoerd, kunt u het schedule:list Artisan commando gebruiken:

php artisan schedule:list

Artisan commando’s plannen

Naast het plannen van closures, kunt u ook Artisan commando’s en systeemcommando’s plannen. U kunt bijvoorbeeld de methode command gebruiken om een Artisan commando in te plannen met de naam van het commando of met de class.

Wanneer u Artisan commando’s inplant met de class naam van het commando, kunt u een array van extra command-line argumenten doorgeven die aan het commando moeten worden meegegeven wanneer het wordt aangeroepen:

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

Taken in wachtrij inplannen

De methode job kan worden gebruikt om een taak in een wachtrij in te plannen. Deze methode biedt een handige manier om in de wachtrij geplaatste jobs te plannen zonder de methode call te gebruiken om sluitingen te definiëren om de job in de wachtrij te plaatsen:

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

Optionele tweede en derde argumenten kunnen aan de methode job worden meegegeven die de wachtrijnaam en de wachtrijverbinding specificeren die moeten worden gebruikt om de job in de wachtrij te plaatsen:

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

Scheduling Shell Commands

De methode exec kan worden gebruikt om een commando aan het besturingssysteem te geven:

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

Schedule Frequency Options

We hebben al een paar voorbeelden gezien van hoe u een taak kunt configureren om op gespecificeerde intervallen uit te voeren. Er zijn echter veel meer taak schema frequenties die u kunt toewijzen aan een taak:

Methode Beschrijving
->cron('* * * * *'); De taak uitvoeren volgens een aangepast cron-schema
->everyMinute(); De taak elke minuut laten uitvoeren
->everyTwoMinutes(); De taak elke twee minuten laten uitvoeren
->everyThreeMinutes(); De taak om de drie minuten uitvoeren
->everyFourMinutes(); De taak om de vier minuten uitvoeren
->everyFiveMinutes(); De taak uitvoeren om de vijf minuten
->everyTenMinutes(); Run de taak om de tien minuten
->everyFifteenMinutes(); Run de taak om de vijftien minuten
->everyThirtyMinutes(); De taak om de dertig minuten uitvoeren
->hourly(); De taak om het uur uitvoeren
->hourlyAt(17); De taak elk uur om 17 minuten na het uur uitvoeren
->everyTwoHours(); De taak elke twee uur uitvoeren
->everyThreeHours(); De taak om de drie uur uitvoeren
->everyFourHours(); De taak om de vier uur uitvoeren
->everySixHours(); De taak uitvoeren om de zes uur
->daily(); De taak elke dag om middernacht uitvoeren
->dailyAt('13:00'); De taak elke dag om 13:00
->twiceDaily(1, 13); De taak dagelijks om 1:00 uitvoeren& 13:00
->weekly(); De taak elke zondag om 00:00 uitvoeren:00
->weeklyOn(1, '8:00'); De taak elke week op maandag om 8:00 uitvoeren
->monthly(); De taak elke eerste dag van de maand om 00 uur uitvoeren:00
->monthlyOn(4, '15:00'); De taak elke maand uitvoeren op de 4e om 15:00
->twiceMonthly(1, 16, '13:00'); De taak elke maand uitvoeren op de 1e en de 16e om 13:00
->twiceMonthly(1, 16, '13:00'); De taak elke maand uitvoeren op de 1e en de 16e om 13:00:00
->lastDayOfMonth('15:00'); De taak uitvoeren op de laatste dag van de maand om 15 uur:00
->quarterly(); De taak op de eerste dag van elk kwartaal om 00 uur laten uitvoeren:00
->yearly(); De taak uitvoeren op de eerste dag van elk jaar om 00:00
->yearlyOn(6, 1, '17:00'); De taak elk jaar uitvoeren op 1 juni om 17:00
->yearlyOn(6, 1, '17:00'); De taak elk jaar uitvoeren op 1 juni om 17:00:00
->timezone('America/New_York'); De tijdzone voor de taak instellen

Deze methoden kunnen worden gecombineerd met extra beperkingen om nog fijnmaziger schema’s te maken die alleen op bepaalde dagen van de week worden uitgevoerd. U kunt bijvoorbeeld een commando plannen dat wekelijks op maandag wordt uitgevoerd:

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

Een lijst met aanvullende beperkingen voor schema’s vindt u hieronder:

Methode Omschrijving
->weekdays(); Limiteer de taak tot weekdagen
->weekends(); Beperk de taak tot weekends
->sundays(); Beperk de taak tot zondag
->mondays(); Beperk de taak tot maandag
->tuesdays(); Beperk de taak tot dinsdag
->wednesdays(); Beperk de taak tot woensdag
->wednesdays(); Beperk de taak tot woensdag
->thursdays(); Limiteer de taak tot donderdag
->fridays(); Limiteer de taak tot vrijdag
->saturdays(); Beperk de taak tot zaterdag
->days(array|mixed); Beperk de taak tot specifieke dagen
->between($startTime, $endTime); Limiteer de taak om te worden uitgevoerd tussen begin- en eindtijd
->unlessBetween($startTime, $endTime); Limiteer de taak om niet te worden uitgevoerd tussen begin- en eindtijd
->unlessBetween($startTime, $endTime); Limiteer de taak om niet te worden uitgevoerd tussen begin- en eindtijd
->when(Closure); Limiteer de taak op basis van een waarheidstest
->environments($env); Limiteer de taak tot specifieke omgevingen

Dagbeperkingen

De methode days kan worden gebruikt om de uitvoering van een taak te beperken tot specifieke dagen van de week. U kunt bijvoorbeeld een opdracht plannen om elk uur op zondag en woensdag te worden uitgevoerd:

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

Als alternatief kunt u de constanten gebruiken die beschikbaar zijn voor de klasse Illuminate\Console\Scheduling\Schedule bij het definiëren van de dagen waarop een taak moet worden uitgevoerd:

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

Between Time Constraints

De methode between kan worden gebruikt om de uitvoering van een taak te beperken op basis van het tijdstip van de dag:

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

Ook kan de methode unlessBetween worden gebruikt om de uitvoering van een taak gedurende een bepaalde periode uit te sluiten:

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

Truth Test Constraints

De methode when kan worden gebruikt om de uitvoering van een taak te beperken op basis van het resultaat van een gegeven waarheidstest. Met andere woorden, als de gegeven afsluiting true teruggeeft, zal de taak worden uitgevoerd zolang geen andere beperkende voorwaarden de taak verhinderen uit te voeren:

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

De methode skip kan worden gezien als het inverse van when. Als de skip-methode true retourneert, wordt de geplande opdracht niet uitgevoerd:

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

Wanneer u geketende when-methoden gebruikt, wordt de geplande opdracht alleen uitgevoerd als alle when-voorwaarden true retourneren.

Omgevingsbeperkingen

De methode environments kan worden gebruikt om taken alleen op de gegeven omgevingen uit te voeren (zoals gedefinieerd door de omgevingsvariabele APP_ENV):

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

Timezones

Met de methode timezone kunt u opgeven dat de tijd van een geplande taak binnen een bepaalde tijdzone moet worden geïnterpreteerd:

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

Als u herhaaldelijk dezelfde tijdzone aan al uw geplande taken toewijst, wilt u misschien een methode scheduleTimezone in uw App\Console\Kernel klasse definiëren. Deze methode moet de standaardtijdzone teruggeven die aan alle geplande taken moet worden toegewezen:

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

{note} Vergeet niet dat sommige tijdzones gebruik maken van zomertijd. Wanneer de zomertijd verandert, kan het zijn dat uw geplande taak twee keer of zelfs helemaal niet wordt uitgevoerd. Daarom raden we u aan tijdzoneplanningen waar mogelijk te vermijden.

Voorkomen dat taken elkaar overlappen

Zelfs als de vorige instantie van de taak nog actief is, worden geplande taken standaard uitgevoerd. Om dit te voorkomen, kunt u de methode withoutOverlapping gebruiken:

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

In dit voorbeeld wordt de emails:send Artisan-opdracht elke minuut uitgevoerd als deze nog niet is uitgevoerd. De methode withoutOverlapping is vooral nuttig als u taken hebt die drastisch variëren in hun uitvoeringstijd, waardoor u niet precies kunt voorspellen hoe lang een bepaalde taak zal duren.

Als dat nodig is, kunt u opgeven hoeveel minuten moeten verstrijken voordat het “zonder overlapping” slot verloopt. Standaard verloopt het slot na 24 uur:

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

Taken op één server uitvoeren

{note} Om deze functie te kunnen gebruiken, moet uw toepassing het database-, memcached-, dynamodb– of redis-cachestuurprogramma gebruiken als het standaard-cachestuurprogramma van uw toepassing. Bovendien moeten alle servers communiceren met dezelfde centrale cachingserver.

Als de planner van uw toepassing op meerdere servers wordt uitgevoerd, kunt u een geplande taak beperken tot slechts één server. Stel dat u bijvoorbeeld een geplande taak hebt die elke vrijdagavond een nieuw rapport genereert. Als de taakplanner op drie werkservers draait, zal de geplande taak op alle drie de servers draaien en het rapport drie keer genereren. Niet goed!

Om aan te geven dat de taak op slechts één server moet draaien, gebruik je de onOneServer methode bij het definiëren van de geplande taak. De eerste server die de taak krijgt, krijgt een atomair slot op de taak om te voorkomen dat andere servers dezelfde taak op hetzelfde moment uitvoeren:

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

Taken op de achtergrond

Zorg er standaard voor dat meerdere taken die op hetzelfde moment zijn gepland, opeenvolgend worden uitgevoerd op basis van de volgorde waarin ze zijn gedefinieerd in uw schedule-methode. Als u langlopende taken hebt, kan dit ertoe leiden dat opeenvolgende taken veel later beginnen dan verwacht. Als u taken op de achtergrond wilt laten lopen, zodat ze allemaal tegelijk kunnen worden uitgevoerd, kunt u de methode runInBackground gebruiken:

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

{note} De methode runInBackground mag alleen worden gebruikt wanneer taken worden gepland via de methoden command en exec.

Onderhoudsmodus

De geplande taken van uw toepassing worden niet uitgevoerd wanneer de toepassing zich in de onderhoudsmodus bevindt, omdat we niet willen dat uw taken het onvoltooide onderhoud dat u mogelijk op uw server uitvoert, verstoren. Als u echter een taak wilt forceren om zelfs in onderhoudsmodus te draaien, kunt u de evenInMaintenanceMode methode aanroepen wanneer u de taak definieert:

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

Running The Scheduler

Nu we hebben geleerd hoe we geplande taken kunnen definiëren, laten we eens bespreken hoe we ze daadwerkelijk op onze server kunnen uitvoeren. Het schedule:run Artisan commando zal al uw geplande taken evalueren en bepalen of ze moeten worden uitgevoerd op basis van de huidige tijd van de server.

Dus, wanneer we Laravel’s scheduler gebruiken, hoeven we slechts een enkel cron configuratie-item aan onze server toe te voegen dat het schedule:run commando elke minuut uitvoert. Als je niet weet hoe je cron entries aan je server moet toevoegen, overweeg dan het gebruik van een service zoals Laravel Forge die de cron entries voor je kan beheren:

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

Running The Scheduler Locally

Typisch gezien zou je geen scheduler cron entry toevoegen aan je lokale ontwikkelmachine. In plaats daarvan kunt u het schedule:work Artisan commando gebruiken. Dit commando draait op de voorgrond en roept de planner elke minuut op totdat u het commando beëindigt:

php artisan schedule:work

Taakuitvoer

De Laravel planner biedt verschillende handige methoden om te werken met de uitvoer die door geplande taken wordt gegenereerd. Ten eerste, met behulp van de sendOutputTo methode, kunt u de uitvoer naar een bestand sturen voor latere inspectie:

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

Als u de uitvoer wilt toevoegen aan een bepaald bestand, kunt u gebruik maken van de appendOutputTo methode:

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

Met behulp van de emailOutputTo methode, kunt u de uitvoer e-mailen naar een e-mail adres van uw keuze. Voordat je de uitvoer van een taak e-mailt, moet je de e-maildiensten van Laravel configureren:

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

Als je de uitvoer alleen wilt e-mailen als de geplande Artisan of systeemopdracht eindigt met een exitcode van nul, gebruik dan de methode emailOutputOnFailure:

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

{note} De methoden emailOutputTo, emailOutputOnFailure, sendOutputTo en appendOutputTo zijn exclusief de methoden command en exec.

Task Hooks

Met de methoden before en after kunt u code opgeven die moet worden uitgevoerd voor en na de uitvoering van de geplande taak:

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

Met de methoden onSuccess en onFailure kunt u code opgeven die moet worden uitgevoerd als de geplande taak slaagt of mislukt. Een mislukking geeft aan dat de geplande Artisan of systeem commando eindigde met een niet-nul exit code:

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

Als er uitvoer beschikbaar is van uw commando, kunt u deze benaderen in uw after, onSuccess of onFailure hooks door een Illuminate\Support\Stringable instantie te typeren als het $output argument van uw hook’s closure definitie:

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

Ping URLs

Met behulp van de pingBefore en thenPing methodes, kan de scheduler automatisch een bepaalde URL pingen voor of nadat een taak is uitgevoerd. Deze methode is handig om een externe service, zoals Envoyer, te laten weten dat uw geplande taak begint of klaar is met uitvoeren:

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

De methoden pingBeforeIf en thenPingIf kunnen worden gebruikt om een bepaalde URL alleen te pingen als een bepaalde voorwaarde true is:

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

De methoden pingOnSuccess en pingOnFailure kunnen worden gebruikt om een bepaalde URL alleen te pingen als de taak slaagt of mislukt. Een mislukking geeft aan dat de geplande Artisan of systeem opdracht eindigde met een niet-nul exit code:

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

Alle ping methoden vereisen de Guzzle HTTP bibliotheek. Guzzle wordt standaard geïnstalleerd in alle nieuwe Laravel projecten, maar je kunt Guzzle handmatig in je project installeren met de Composer package manager als het per ongeluk is verwijderd:

composer require guzzlehttp/guzzle