Event::dispatch() and the EventServiceProvider
Concept
Event subscribers group multiple event listeners for related events into a single class. Instead of creating separate listener classes for each event, a subscriber class defines a subscribe() method that registers which methods handle which events.
When to use subscribers: When multiple events are logically related and handled by the same "system". Example: an OrderEventSubscriber handling OrderPlaced, OrderShipped, OrderCancelled — all order lifecycle events.
Structure:
class OrderEventSubscriber
{
public function handleOrderPlaced(OrderPlaced $event): void { ... }
public function handleOrderShipped(OrderShipped $event): void { ... }
public function subscribe(Dispatcher $events): void
{
$events->listen(OrderPlaced::class, [static::class, 'handleOrderPlaced']);
$events->listen(OrderShipped::class, [static::class, 'handleOrderShipped']);
}
}Registering: Add to EventServiceProvider::$subscribe array.
Return array form: The subscribe() method can return an array mapping events to methods — a cleaner syntax:
public function subscribe(): array
{
return [
OrderPlaced::class => 'handleOrderPlaced',
OrderShipped::class => 'handleOrderShipped',
];
}Subscribers vs multiple listeners: Both work. Subscribers are cleaner when one class logically handles all events of a domain area. Multiple listeners are better when reactions are independent and may need different configurations (different queues, retries).
Code Example
<?php
namespace App\Listeners;
use App\Events\{OrderPlaced, OrderShipped, OrderCancelled, OrderRefunded};
use Illuminate\Events\Dispatcher;
class OrderEventSubscriber
{
public function handleOrderPlaced(OrderPlaced $event): void
{
\Illuminate\Support\Facades\Log::info('Order placed', ['id' => $event->order->id]);
// Send confirmation email, update CRM, etc.
}
public function handleOrderShipped(OrderShipped $event): void
{
\Illuminate\Support\Facades\Mail::to($event->order->customer)
->send(new \App\Mail\ShippingNotification($event->order, $event->trackingNumber));
}
public function handleOrderCancelled(OrderCancelled $event): void
{
// Restore inventory, notify warehouse
foreach ($event->order->items as $item) {
$item->product->increment('stock', $item->quantity);
}
}
public function handleOrderRefunded(OrderRefunded $event): void
{
\Illuminate\Support\Facades\Log::info('Refund processed', [
'order_id' => $event->order->id,
'amount' => $event->amount,
]);
}
// Register all handlers — return array form (Laravel 9+)
public function subscribe(): array
{
return [
OrderPlaced::class => 'handleOrderPlaced',
OrderShipped::class => 'handleOrderShipped',
OrderCancelled::class => 'handleOrderCancelled',
OrderRefunded::class => 'handleOrderRefunded',
];
}
// Alternatively — manual Dispatcher form
// public function subscribe(Dispatcher $events): void
// {
// $events->listen(OrderPlaced::class, [static::class, 'handleOrderPlaced']);
// $events->listen(OrderShipped::class, [static::class, 'handleOrderShipped']);
// }
}
// EventServiceProvider
class EventServiceProvider extends \Illuminate\Foundation\Support\Providers\EventServiceProvider
{
protected $subscribe = [
\App\Listeners\OrderEventSubscriber::class,
\App\Listeners\UserActivitySubscriber::class,
];
}