Cadence від Steve Bauman пропонує новий підхід до планування завдань у Laravel. Замість того, щоб описувати всі заплановані таски в одному файлі, пакет дозволяє прив’язувати один або кілька графіків безпосередньо до екземплярів моделей Eloquent. Кожен графік має власну періодичність і часовий пояс, а під час настання події система автоматично запускає відповідні івенти.
# Як це працює
Після встановлення пакета та виконання міграцій у базі з'являється таблиця schedules. Вона містить поліморфне посилання на будь-яку модель, вираз розкладу, опціональний часовий пояс, а також автоматично розраховані мітки часу next_run_at та last_run_at.
Щоб активувати функціонал, додайте інтерфейс Schedulable та трейт HasSchedules до вашої моделі:
use DirectoryTree\Cadence\HasSchedules;
use DirectoryTree\Cadence\Schedulable;
class Subscription extends Model implements Schedulable
{
use HasSchedules;
}
Тепер ви можете призначити розклад конкретному об’єкту. Cadence підтримує драйвери для cron-виразів та RRULE-патернів — вам потрібно лише встановити відповідні бібліотеки:
# Для cron-виразів
composer require dragonmantank/cron-expression
# Для RRULE (оберіть одну)
composer require rlanvin/php-rrule
# або
composer require simshaun/recurr
Звичайний cron-розклад виглядає так:
use DirectoryTree\Cadence\Drivers\CronSchedule;
// Виставляти рахунок за підписку першого числа кожного місяця о півночі
$subscription->addSchedule(new CronSchedule('0 0 1 * *'));
Для складніших сценаріїв зручніше використовувати RRULE — він дає набагато більше контролю над повтореннями, які важко описати через cron:
use DirectoryTree\Cadence\Drivers\RruleSchedule;
// Кожні два тижні по вівторках та четвергах
$subscription->addSchedule(new RruleSchedule('FREQ=WEEKLY;INTERVAL=2;BYDAY=TU,TH'));
Графіки враховують часові пояси, тому користувачі в різних регіонах отримуватимуть сповіщення або оновлення у правильний локальний час:
$subscription->addSchedule(
new CronSchedule('0 8 * * 1', 'Australia/Sydney') // Щопонеділка о 8 ранку за часом Сіднея
);
# Запуск та обробка подій
Cadence надає Artisan-команду schedules:run, яку потрібно зареєструвати у стандартному планувальнику Laravel для щохвилинного виконання:
// routes/console.php
Schedule::command('schedules:run')->withoutOverlapping()->everyMinute();
Щохвилини команда знаходить усі записи, де час next_run_at уже настав, генерує подію ScheduleTriggered і оновлює дату наступного запуску. Ваш застосунок може реагувати на це через звичайний listener:
use DirectoryTree\Cadence\Events\ScheduleTriggered;
class ProcessDueSubscription
{
public function handle(ScheduleTriggered $event): void
{
$subscription = $event->schedule->schedulable;
$subscription->processRenewal();
}
}
Подія містить об’єкт графіка, що дає доступ до батьківської моделі, виразу та часових міток. Це дозволяє гнучко логувати дії або розділяти логіку залежно від типу моделі.
# Розширюваність
Якщо стандартних cron або RRULE недостатньо, ви можете створити власний драйвер. Для цього розширте базовий клас Schedule та імплементуйте метод resolveNextOccurrence(). Він отримує CarbonInterface і має повернути час наступного виконання. Драйвери реєструються за назвою, тому їх легко замінювати чи доповнювати.
Детальнішу інформацію та вихідний код можна знайти на GitHub.