Observer (Спостерігач) - об'єкт-«видавець» повідомляє про зміну стану всіх зацікавлених «підписників», не знаючи про них нічого конкретного. Підписники реєструються самі.
Проблема, яку він розв'язує:
public function pay(Order $order): void
{
$order->markAsPaid();
$this->mailer->sendReceipt($order);
$this->warehouse->reserve($order);
$this->analytics->trackPurchase($order);
$this->crm->updateCustomer($order->customer);
// кожна нова реакція - правка цього методу
}
Оплата «знає» про пошту, склад, аналітику й CRM. Зміни в будь-якій з цих систем зачіпають код оплати.
З Observer (у Laravel - події й слухачі):
public function pay(Order $order): void
{
$order->markAsPaid();
OrderPaid::dispatch($order);
}
class SendReceipt { public function handle(OrderPaid $event): void { /* ... */ } }
class ReserveStock { public function handle(OrderPaid $event): void { /* ... */ } }
Laravel знаходить слухачів автоматично за типом події в методі handle. Нова реакція - новий клас-слухач, код оплати не змінюється.
Інші реалізації Observer у Laravel:
- спостерігачі моделей (
#[ObservedBy(OrderObserver::class)]) - реакція наcreated,updated,deleted; - події моделей (
static::created(...)); - трансляція подій у браузер (
ShouldBroadcast) - підписники навіть в іншому процесі; Livewire#[On]і події JavaScript - та сама ідея на клієнті.
Переваги: слабка зв'язність, легко додавати реакції, слухачі можна виконувати в черзі (ShouldQueue).
Недоліки й пастки:
- неявний потік: з коду
OrderPaid::dispatch()не видно, що станеться далі - треба шукати слухачів (php artisan event:list); - порядок виконання слухачів не варто вважати гарантованим для бізнес-логіки;
- спостерігачі моделей спрацьовують на кожне збереження, включно з сидерами, імпортом, тестами - і не спрацьовують на масові запити (
Order::where(...)->update()); - транзакції: подія, оброблена до коміту, може відправити лист про замовлення, яке потім відкотиться -
ShouldDispatchAfterCommitчиafterCommitдля слухачів у черзі.
Коли не варто: якщо дія - обов'язкова частина сценарію (без неї операція неуспішна), її краще викликати явно, а не ховати в слухачі.