Подія повідомляє: «сталося X». Слухачі реагують, і відправник про них не знає.
// у дії оформлення замовлення
OrderPlaced::dispatch($order);
// окремо - реакції
class SendOrderConfirmation { public function handle(OrderPlaced $event): void { /* лист */ } }
class NotifyWarehouse implements ShouldQueue { public function handle(OrderPlaced $event): void { /* API складу */ } }
class TrackPurchase implements ShouldQueue { /* аналітика */ }
Коли події доречні:
- побічні реакції, без яких основна дія все одно успішна: листи, сповіщення, аналітика, оновлення пошукового індексу, кешу, синхронізація зі сторонніми системами;
- кілька незалежних реакцій на одну подію, які додаються з часом;
- розв'язка модулів: модуль «Склад» реагує на
OrderPlacedз модуля «Замовлення», не будучи залежністю для нього; - асинхронність: слухачі з
ShouldQueueвиконуються в черзі, не сповільнюючи відповідь.
Коли краще прямий виклик:
- дія - обов'язкова частина сценарію, і її збій має зупинити операцію (списання оплати, резервування товару) - прямий виклик з явною обробкою помилок;
- результат потрібен одразу у викликаючому коді;
- одна реакція, яка навряд чи зміниться, - подія лише додасть непрямість.
Ознака надмірного використання: щоб зрозуміти, що відбувається при оформленні замовлення, треба відкрити десять слухачів, які генерують ще події. Потік стає невидимим.
Важливі деталі:
- транзакції: подія, оброблена до коміту, може надіслати лист про замовлення, яке потім відкотиться. Використовуйте
ShouldDispatchAfterCommitдля подій іafterCommit/ShouldHandleEventsAfterCommitдля слухачів; - дані в події - мінімально потрібні (модель чи ідентифікатор), не весь контекст запиту;
- події моделей (
created,updated) зручні, але спрацьовують і в сидерах, імпорті, тестах і не спрацьовують на масовихupdate()- для бізнес-подій краще явні доменні події (OrderPlaced), а неOrderCreatedз Eloquent; - перелік:
php artisan event:listпоказує, хто на що підписаний.