Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Events

After registration you need to send an email, award a bonus, record statistics. If all of that goes into the controller, it balloons. An event announces "a user registered", and listeners decide what to do about it. The main code knows nothing about them.

An event

An event is a simple class holding data:

php artisan make:event OrderPlaced
namespace App\Events;
 
use App\Models\Order;
use Illuminate\Foundation\Events\Dispatchable;
 
class OrderPlaced
{
    use Dispatchable;
 
    public function __construct(public Order $order) {}
}

A listener

A listener performs one action in response to an event:

php artisan make:listener SendOrderConfirmation --event=OrderPlaced
namespace App\Listeners;
 
use App\Events\OrderPlaced;
use App\Mail\OrderConfirmation;
use Illuminate\Support\Facades\Mail;
 
class SendOrderConfirmation
{
    public function handle(OrderPlaced $event): void
    {
        Mail::to($event->order->user)->queue(new OrderConfirmation($event->order));
    }
}

Laravel finds listeners in the app/Listeners folder by itself and ties them to an event by the parameter type of the handle() method.

Dispatching an event

use App\Events\OrderPlaced;
 
public function store(Request $request)
{
    $order = Order::create([...]);
 
    OrderPlaced::dispatch($order);
 
    return redirect()->route('orders.show', $order);
}

The controller only reports what happened. To add a new action you write one more listener — the controller stays untouched.

Several listeners

Any number of listeners can respond to one event:

ListenerWhat it does
SendOrderConfirmationEmails the customer
NotifyWarehouseTells the warehouse
UpdateSalesStatisticsUpdates the statistics

A queued listener

A slow listener runs in the background — just add the interface:

use Illuminate\Contracts\Queue\ShouldQueue;
 
class NotifyWarehouse implements ShouldQueue
{
    public function handle(OrderPlaced $event): void
    {
        // a request to the warehouse system
    }
}

Built-in events

Laravel fires events of its own at important moments: Registered after registration, Login on login, PasswordReset when a password changes. You subscribe to them the same way as to your own:

use Illuminate\Auth\Events\Login;
 
class RecordLastLogin
{
    public function handle(Login $event): void
    {
        $event->user->update(['last_login_at' => now()]);
    }
}

The list of events

php artisan event:list

The command shows every event and its listeners.

Common mistake

Events make the connections in code implicit: the controller does not show that three emails go out after an order. Use them for side effects without which the main operation would still have happened. If an order cannot exist without deducting stock, that is part of the main logic — it belongs in the checkout code, not in a listener.

Thanks for reading!

Donate to the site — we work hard for you.