• Introduction
  • Définition des planifications
    • Planification des commandes Artisan
    • Planification des tâches en file d’attente
    • Planification des commandes Shell
    • Options de fréquence de planification
    • Tones horaires
    • Prévenir les chevauchements de tâches
    • .

    • Exécution de tâches sur un serveur
    • Tâches d’arrière-plan
    • Mode maintenance
  • Exécution du planificateur
    • Exécution du planificateur localement
  • Sortie de tâche
  • Crochets de tâche

Introduction

Dans le passé, vous avez peut-être écrit une entrée de configuration cron pour chaque tâche que vous deviez planifier sur votre serveur. Cependant, cela peut rapidement devenir une douleur parce que votre planification des tâches n’est plus dans le contrôle de la source et vous devez SSH dans votre serveur pour voir vos entrées cron existantes ou ajouter des entrées supplémentaires.

Le planificateur de commande de Laravelle offre une approche nouvelle de la gestion des tâches planifiées sur votre serveur. Le planificateur vous permet de définir de manière fluide et expressive votre planification de commande au sein même de votre application Laravel. Lorsque vous utilisez le planificateur, une seule entrée cron est nécessaire sur votre serveur. La planification de vos tâches est définie dans la méthode schedule du fichier app/Console/Kernel.php. Pour vous aider à démarrer, un exemple simple est défini dans la méthode.

Définir les planifications

Vous pouvez définir toutes vos tâches planifiées dans la méthode schedule de la classe App\Console\Kernel de votre application. Pour commencer, jetons un coup d’œil à un exemple. Dans cet exemple, nous allons programmer une fermeture qui sera appelée tous les jours à minuit. Dans la fermeture, nous exécuterons une requête de base de données pour effacer une table:

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

En plus de la planification à l’aide de fermetures, vous pouvez également planifier des objets invocables. Les objets invocables sont des classes PHP simples qui contiennent une méthode __invoke:

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

Si vous souhaitez afficher une vue d’ensemble de vos tâches planifiées et de leur prochaine exécution, vous pouvez utiliser la commande schedule:list Artisan:

php artisan schedule:list

Planification des commandes Artisan

En plus de la planification des fermetures, vous pouvez également planifier les commandes Artisan et les commandes système. Par exemple, vous pouvez utiliser la méthode command pour planifier une commande Artisan en utilisant le nom ou la classe de la commande.

Lorsque vous planifiez des commandes Artisan en utilisant le nom de la classe de la commande, vous pouvez passer un tableau d’arguments de ligne de commande supplémentaires qui doivent être fournis à la commande lorsqu’elle est invoquée:

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

Planification de travaux en file d’attente

La méthode job peut être utilisée pour planifier un travail en file d’attente. Cette méthode fournit un moyen pratique de planifier des travaux en file d’attente sans utiliser la méthode call pour définir des fermetures pour mettre le travail en file d’attente :

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

Des deuxième et troisième arguments facultatifs peuvent être fournis à la méthode job qui spécifie le nom de la file d’attente et la connexion à la file d’attente qui doivent être utilisés pour mettre le travail en file d’attente :

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

Commandes Shell de planification

La méthode exec peut être utilisée pour émettre une commande au système d’exploitation :

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

Options de fréquence de planification

Nous avons déjà vu quelques exemples de la façon dont vous pouvez configurer une tâche pour qu’elle s’exécute à des intervalles spécifiés. Cependant, il existe de nombreuses autres fréquences de planification de tâches que vous pouvez affecter à une tâche :

.

.

Méthode Description
->cron('* * * * *'); Exécuter la tâche sur une planification cron personnalisée
->everyMinute(); Exécuter la tâche toutes les minutes
->everyTwoMinutes(); Exécuter la tâche toutes les deux minutes
->everyThreeMinutes(); Exécuter la tâche toutes les trois minutes
->everyFourMinutes(); Exécuter la tâche toutes les quatre minutes
->everyFiveMinutes(); Exécuter la tâche toutes les cinq minutes
->everyTenMinutes(); Exécuter la tâche toutes les dix minutes
->everyFifteenMinutes(); Exécuter la tâche toutes les quinze minutes
->everyThirtyMinutes(); Exécuter la tâche toutes les trente minutes
->hourly(); Exécuter la tâche toutes les heures
->hourlyAt(17); Exécuter la tâche toutes les heures à 17 minutes de l’heure
->everyTwoHours(); Exécuter la tâche toutes les deux heures
->everyThreeHours(); Exécuter la tâche toutes les trois heures
->everyFourHours(); Exécuter la tâche toutes les quatre heures
->everySixHours(); Exécuter la tâche toutes les six heures
->daily(); Exécuter la tâche tous les jours à minuit
->dailyAt('13:00'); Exécuter la tâche tous les jours à 13 :00
->twiceDaily(1, 13); Exécuter la tâche chaque jour à 1:00 & 13:00
->weekly(); Exécuter la tâche chaque dimanche à 00 :00
->weeklyOn(1, '8:00'); Exécuter la tâche chaque semaine le lundi à 8:00
->monthly(); Exécuter la tâche le premier jour de chaque mois à 00 :00
->monthlyOn(4, '15:00'); Exécuter la tâche tous les mois le 4 à 15:00
->twiceMonthly(1, 16, '13:00'); Exécuter la tâche tous les mois le 1er et le 16 à 13 :00
->lastDayOfMonth('15:00'); Lancer la tâche le dernier jour du mois à 15 :00
->quarterly(); Lancer la tâche le premier jour de chaque trimestre à 00 :00
->yearly(); Exécuter la tâche le premier jour de chaque année à 00:00
->yearlyOn(6, 1, '17:00'); Exécuter la tâche chaque année le 1er juin à 17 :00
->timezone('America/New_York'); Définir le fuseau horaire pour la tâche

Ces méthodes peuvent être combinées avec des contraintes supplémentaires pour créer des planifications encore plus fines qui ne s’exécutent que certains jours de la semaine. Par exemple, vous pouvez programmer une commande pour qu’elle s’exécute chaque semaine le lundi :

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

Une liste de contraintes de programmation supplémentaires peut être trouvée ci-dessous :

.

.

.

Méthode Description
->weekdays(); Limiter la tâche aux jours de la semaine
->weekends(); Limiter la tâche aux week-ends
->sundays(); Limiter la tâche au dimanche
->mondays(); Limiter la tâche au lundi
->tuesdays(); Limiter la tâche au mardi
->wednesdays(); Limiter la tâche au mercredi
->thursdays(); Limite la tâche au jeudi
->fridays(); Limite la tâche au vendredi
->saturdays(); Limiter la tâche au samedi
->days(array|mixed); Limiter la tâche à des jours spécifiques
->between($startTime, $endTime); Limiter la tâche à s’exécuter entre les heures de début et de fin
->unlessBetween($startTime, $endTime); Limiter la tâche à ne pas s’exécuter entre les heures de début et de fin
->when(Closure); Limiter la tâche en fonction d’un test de vérité
->environments($env); Limiter la tâche à des environnements spécifiques environnements

Contraintes de jour

La méthode days peut être utilisée pour limiter l’exécution d’une tâche à des jours spécifiques de la semaine. Par exemple, vous pouvez programmer une commande pour qu’elle s’exécute toutes les heures les dimanches et les mercredis :

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

Alternativement, vous pouvez utiliser les constantes disponibles sur la classe Illuminate\Console\Scheduling\Schedule lors de la définition des jours auxquels une tâche doit s’exécuter :

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

Contraintes d’intervalle de temps

La méthode between peut être utilisée pour limiter l’exécution d’une tâche en fonction de l’heure de la journée :

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

De même, la méthode unlessBetween peut être utilisée pour exclure l’exécution d’une tâche pendant une période de temps :

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

Contraintes de test de vérité

La méthode when peut être utilisée pour limiter l’exécution d’une tâche en fonction du résultat d’un test de vérité donné. En d’autres termes, si la fermeture donnée renvoie true, la tâche s’exécutera tant qu’aucune autre condition contraignante ne l’empêche de s’exécuter :

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

La méthode skip peut être considérée comme l’inverse de when. Si la méthode skip renvoie true, la tâche planifiée ne sera pas exécutée:

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

Lorsque l’on utilise des méthodes when enchaînées, la commande planifiée ne s’exécutera que si toutes les conditions when renvoient true.

Contraintes d’environnement

La méthode environments peut être utilisée pour exécuter des tâches uniquement sur les environnements donnés (tels que définis par la variable d’environnement APP_ENV) :

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

Timezones

À l’aide de la méthode timezone, vous pouvez spécifier que l’heure d’une tâche planifiée doit être interprétée dans un fuseau horaire donné :

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

Si vous attribuez de manière répétée le même fuseau horaire à toutes vos tâches planifiées, vous pouvez définir une méthode scheduleTimezone dans votre classe App\Console\Kernel. Cette méthode devrait retourner le fuseau horaire par défaut qui devrait être attribué à toutes les tâches planifiées:

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

{note}. N’oubliez pas que certains fuseaux horaires utilisent l’heure d’été. Lorsque les changements d’heure d’été se produisent, votre tâche planifiée peut s’exécuter deux fois ou même ne pas s’exécuter du tout. Pour cette raison, nous recommandons d’éviter la planification des fuseaux horaires lorsque cela est possible.

Prévenir les chevauchements de tâches

Par défaut, les tâches planifiées seront exécutées même si l’instance précédente de la tâche est toujours en cours d’exécution. Pour empêcher cela, vous pouvez utiliser la méthode withoutOverlapping:

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

Dans cet exemple, la commande emails:send Artisan sera exécutée toutes les minutes si elle n’est pas déjà en cours d’exécution. La méthode withoutOverlapping est particulièrement utile si vous avez des tâches qui varient drastiquement dans leur temps d’exécution, vous empêchant de prédire exactement combien de temps une tâche donnée prendra.

Si nécessaire, vous pouvez spécifier combien de minutes doivent s’écouler avant que le verrou « sans chevauchement » expire. Par défaut, le verrou expire après 24 heures :

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

Exécution de tâches sur un seul serveur

{note}. Pour utiliser cette fonctionnalité, votre application doit utiliser le pilote de cache database, memcached, dynamodb ou redis comme pilote de cache par défaut de votre application. En outre, tous les serveurs doivent communiquer avec le même serveur de cache central.

Si le planificateur de votre application s’exécute sur plusieurs serveurs, vous pouvez limiter un travail planifié pour qu’il ne s’exécute que sur un seul serveur. Par exemple, supposons que vous ayez une tâche planifiée qui génère un nouveau rapport chaque vendredi soir. Si le planificateur de tâches est exécuté sur trois serveurs de travailleurs, la tâche planifiée s’exécutera sur les trois serveurs et générera le rapport trois fois. Pas bon!

Pour indiquer que la tâche doit s’exécuter sur un seul serveur, utilisez la méthode onOneServer lors de la définition de la tâche planifiée. Le premier serveur à obtenir la tâche sécurisera un verrou atomique sur la tâche pour empêcher les autres serveurs d’exécuter la même tâche en même temps :

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

Tâches d’arrière-plan

Par défaut, plusieurs tâches planifiées en même temps s’exécuteront séquentiellement en fonction de l’ordre dans lequel elles sont définies dans votre méthode schedule. Si vous avez des tâches à longue durée d’exécution, cela peut entraîner le démarrage des tâches suivantes beaucoup plus tard que prévu. Si vous souhaitez exécuter des tâches en arrière-plan afin qu’elles puissent toutes s’exécuter simultanément, vous pouvez utiliser la méthode runInBackground:

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

{note}. La méthode runInBackground ne peut être utilisée que lors de la planification de tâches via les méthodes command et exec.

Mode maintenance

Les tâches planifiées de votre application ne s’exécuteront pas lorsque l’application est en mode maintenance, car nous ne voulons pas que vos tâches interfèrent avec toute maintenance non terminée que vous pourriez effectuer sur votre serveur. Cependant, si vous souhaitez forcer l’exécution d’une tâche même en mode maintenance, vous pouvez appeler la méthode evenInMaintenanceMode lors de la définition de la tâche :

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

Exécution du planificateur

Maintenant que nous avons appris à définir les tâches planifiées, discutons de la manière de les exécuter réellement sur notre serveur. La commande schedule:run Artisan évaluera toutes vos tâches planifiées et déterminera si elles doivent être exécutées en fonction de l’heure actuelle du serveur.

Donc, lorsque nous utilisons le planificateur de Laravel, nous n’avons qu’à ajouter une seule entrée de configuration cron à notre serveur qui exécute la commande schedule:run toutes les minutes. Si vous ne savez pas comment ajouter des entrées cron à votre serveur, envisagez d’utiliser un service tel que Laravel Forge qui peut gérer les entrées cron pour vous :

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

Exécuter l’ordonnanceur localement

Typiquement, vous n’ajouteriez pas une entrée cron de l’ordonnanceur à votre machine de développement locale. Au lieu de cela, vous pouvez utiliser la commande schedule:work Artisan. Cette commande s’exécutera en avant-plan et invoquera le planificateur toutes les minutes jusqu’à ce que vous terminiez la commande:

php artisan schedule:work

Sortie de la tâche

Le planificateur Laravel fournit plusieurs méthodes pratiques pour travailler avec la sortie générée par les tâches planifiées. Tout d’abord, en utilisant la méthode sendOutputTo, vous pouvez envoyer la sortie dans un fichier pour une inspection ultérieure:

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

Si vous souhaitez ajouter la sortie à un fichier donné, vous pouvez utiliser la méthode appendOutputTo:

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

En utilisant la méthode emailOutputTo, vous pouvez envoyer la sortie par courriel à une adresse électronique de votre choix. Avant d’envoyer par courriel la sortie d’une tâche, vous devez configurer les services de courriel de Laravel:

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

Si vous voulez seulement envoyer par courriel la sortie si la commande Artisan ou système planifiée se termine avec un code de sortie non nul, utilisez la méthode emailOutputOnFailure:

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

{note}. Les méthodes emailOutputTo, emailOutputOnFailure, sendOutputTo et appendOutputTo sont exclusives aux méthodes command et exec.

Crochets de tâche

À l’aide des méthodes before et after, vous pouvez spécifier le code à exécuter avant et après l’exécution de la tâche planifiée :

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

Les méthodes onSuccess et onFailure vous permettent de spécifier le code à exécuter si la tâche planifiée réussit ou échoue. Un échec indique que la commande programmée d’Artisan ou du système s’est terminée avec un code de sortie non nul :

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

Si la sortie est disponible à partir de votre commande, vous pouvez y accéder dans vos hooks after, onSuccess ou onFailure en indiquant le type d’une instance Illuminate\Support\Stringable comme argument $output de la définition de fermeture de votre hook :

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

Pinging d’URL

À l’aide des méthodes pingBefore et thenPing, l’ordonnanceur peut pinguer automatiquement une URL donnée avant ou après l’exécution d’une tâche. Cette méthode est utile pour notifier à un service externe, tel que Envoyer, que votre tâche planifiée commence ou a terminé son exécution :

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

Les méthodes pingBeforeIf et thenPingIf peuvent être utilisées pour envoyer un ping à une URL donnée uniquement si une condition donnée est true:

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

Les méthodes pingOnSuccess et pingOnFailure peuvent être utilisées pour envoyer un ping à une URL donnée uniquement si la tâche réussit ou échoue. Un échec indique que la commande Artisan ou système programmée s’est terminée avec un code de sortie non nul :

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

Toutes les méthodes ping nécessitent la bibliothèque HTTP Guzzle. Guzzle est généralement installé par défaut dans tous les nouveaux projets Laravel, mais, vous pouvez installer manuellement Guzzle dans votre projet à l’aide du gestionnaire de paquets Composer s’il a été supprimé accidentellement :

composer require guzzlehttp/guzzle

.