Laravel Tutorial · Beyond the Basics · Lesson 23 of 27

Events, Listeners and Notifications

Decouple your code with events and listeners, and send notifications to users over mail, database, SMS or Slack channels.

Create a free account to save this page, take notes and track your progress. Sign in

Events and listeners

When something happens ("an order was placed"), fire an event; any number of listeners react (send a receipt, update stock, notify the warehouse) without the order code knowing about them.

php artisan make:event OrderPlaced
php artisan make:listener SendOrderReceipt --event=OrderPlaced

Listeners are discovered automatically from type hints, or registered with Event::listen(...). A listener implementing ShouldQueue runs in the background. Eloquent fires model events (created, updated, deleted) you can observe too.

Notifications

A notification sends one message over several channels: mail, database (an in-app inbox), broadcast, SMS or Slack. Users get them with $user->notify(new OrderShipped($order)).

One event, several listeners
<?php
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Support\Facades\Event;

class OrderPlaced
{
    use Dispatchable;   // adds OrderPlaced::dispatch(...)

    public function __construct(public string $orderId, public float $total) {}
}

class SendOrderReceipt
{
    public function handle(OrderPlaced $event): void
    {
        echo "  receipt emailed for {$event->orderId}\n";
    }
}

class UpdateStock
{
    public function handle(OrderPlaced $event): void
    {
        echo "  stock reserved for {$event->orderId}\n";
    }
}

Event::listen(OrderPlaced::class, SendOrderReceipt::class);
Event::listen(OrderPlaced::class, UpdateStock::class);
Event::listen(OrderPlaced::class, function (OrderPlaced $event) {
    if ($event->total > 100) {
        echo "  big order alert: {$event->orderId}\n";
    }
});

echo "placing A-100 (49.90):\n";
OrderPlaced::dispatch('A-100', 49.90);
echo "placing A-101 (250.00):\n";
event(new OrderPlaced('A-101', 250.00));

Event::fake([OrderPlaced::class]);            // in tests: capture events instead of running listeners
OrderPlaced::dispatch('A-102', 10.00);
Event::assertDispatched(OrderPlaced::class, fn ($e) => $e->orderId === 'A-102');
echo "test assertion passed: OrderPlaced was dispatched for A-102\n";

Output

placing A-100 (49.90):
  receipt emailed for A-100
  stock reserved for A-100
placing A-101 (250.00):
  receipt emailed for A-101
  stock reserved for A-101
  big order alert: A-101
test assertion passed: OrderPlaced was dispatched for A-102

Run this on your computer — see “Get Started” for setup.

Test yourself

What's the main benefit of events and listeners?

  1. Faster SQL
  2. Code that triggers something doesn't need to know everything that reacts to it
  3. They replace validation
  4. They cache responses
Show answer

Answer: Code that triggers something doesn't need to know everything that reacts to it

Was this page helpful?