Les tâches planifiées dans Laravel

Il arrive parfois que vous deviez exécuter une tâche planifiée d’avance. Par exemple, vous pouvez avoir besoin d’exporter vers un fichier Excel tous les soirs, ou d’envoyer un rappel à un utilisateur à une certaine heure. Une solution possible serait de créer une commande ou un script Cron pour planifier pour chacune de ces tâches séparément, mais cela pourrait devenir difficile à maintenir, surtout s’il y a beaucoup de tâches planifiées. Heureusement, Laravel possède un planificateur de tâches intégré qui permet de définir les planifications à même l’application, et de les exécuter avec une seule tâche Cron.

Les tâches planifiées dans Laravel

Définition des planifications

Les planifications sont définies dans la méthode schedule de la classe App\Console\Kernal. Par exemple, supposons que nous ayons une méthode pour archiver les anciennes commandes que nous voulons exécuter au début de chaque mois. Nous pourrions la définir comme suit :

<?php

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use App\Models\Order;

class Kernel extends ConsoleKernel
{
    /**
     * Define the application's command schedule.
     */
    protected function schedule(Schedule $schedule): void
    {
        $schedule->call(function () {
            Order::archive();
        })->monthly();
    }
}

Il existe différentes façons de définir les planifications :

  • Fermetures : Comme nous l’avons vu dans l’exemple ci-dessus, vous pouvez utiliser la méthode call pour lancer une fermeture qui exécutera le code programmé.
  • Objets invocables : Les classes PHP qui contiennent une méthode __invoke peuvent également être exécutées à l’aide de la méthode call. Par exemple, pour un objet appelé OrderArchive qui gère la logique d’archivage, vous pouvez définir la planification en utilisant $schedule->call(new OrderArchive())->monthly().
  • Commandes : La méthode command permet de planifier une commande Artisan ou une commande système. Par exemple, pour exécuter une commande appelée archive:orders pour effectuer l’archivage, vous pouvez définir la planification en utilisant $schedule->command('archive:orders')->monthly().
  • Files d’attente : En utilisant la méthode job, vous pouvez planifier l’exécution d’une tâche en file d’attente. Par exemple, pour exécuter une tâche appelée ArchiveOrders pour effectuer l’archivage, vous pouvez définir la planification en utilisant $schedule->job(new ArchiveOrders)->monthly().

Fréquence des planifications

Le planificateur de Laravel dispose de plus de 30 méthodes pour définir la fréquence d’exécution des tâches planifiées. Nous ne les énumérerons pas toutes ici, mais voici quelques exemples :

  • everyMinute();
  • everyFiveMinutes();
  • hourly();
  • hourlyAt(20);
  • daily();
  • dailyAt(’13:00′);
  • weekly();
  • weeklyOn(1, ‘8:00’);
  • monthly();
  • twiceMonthly(1, 16, ’13:00′);
  • yearly();

Contraintes des planifications

Vous pouvez imposer des contraintes supplémentaires aux planifications. Par exemple, pour programmer une notification qui n’est envoyée que pendant les heures de travail, vous pouvez faire quelque chose comme ceci :

$schedule->call(function () {
	User::sendNotification();
})->hourly()
	->weekdays()
	->between("8:00", "18:00");

Pour une liste complète des fréquences et des contraintes, visitez cette page de la documentation Laravel (en anglais).

Si aucune des fréquences ou contraintes fournies ne permet de créer la planification souhaitée, et que tu es familier avec l’écriture d’expressions Cron, vous pouvez utiliser la méthode Cron en utilisant les expressions souhaitées.

À titre d’exemple, cette fonction doit s’exécuter toutes les cinq minutes à partir de 13 h et jusqu’à 13 h 55, puis à partir de 18 h et jusqu’à 18 h 55 tous les jours :

$schedule->call(function() {
	//Add schedule code here
})->cron('0/5 13,18 * * ?');

Le planificateur de tâches de Laravel peut être exécuté manuellement à l’aide de la commande schedule:run. Dans un environnement de production, c’est une tâche Cron qui exécutera généralement artisan artisan schedule:run une fois par minute.

Dans un environnement de développement, il n’y aura généralement pas de tâche Cron définie. À la place, la commande schedule:work exécuterait la commande schedule:run une fois par minute.

Autres options pour les planifications

Le planificateur de tâches de Laravel dispose d’autres options qui peuvent être utiles dans certaines circonstances. Par exemple, pour une tâche qui doit être exécutée toutes les quelques minutes, mais qui pourrait avoir un temps d’exécution très variable, il est possible d’utiliser la méthode withoutOverlapping() pour empêcher la tâche de s’exécuter si l’instance précédente de la tâche est toujours en cours d’exécution. De même, pour une tâche qui prend beaucoup de temps à s’exécuter, il est possible d’utiliser la méthode runInBackground() pour qu’elle n’empêche pas d’autres tâches de s’exécuter avant qu’elle ne soit terminée. Dans un environnement qui comprend plusieurs serveurs, il est possible d’utiliser onOneServer() pour exécuter la tâche sur un seul serveur.

Pour plus de détails sur le planificateur de tâches de Laravel, consultez la documentation de Laravel (en anglais).