Laravel Events and Listeners in 2026: Event-Driven Architecture and Interview Questions
Master Laravel events and listeners with automatic discovery, queued listeners, and event subscribers. Covers Laravel 12 patterns and common interview questions.

Laravel events and listeners implement the observer pattern, decoupling components by letting parts of an application react to actions without direct dependencies. When a user places an order, the OrderShipped event fires, and separate listeners handle notifications, analytics, and inventory updates independently.
Laravel 12 automatically discovers listeners in app/Listeners. Any class with a handle or __invoke method type-hinting an event class gets registered automatically, no configuration file needed.
How Laravel Event Discovery Works in Version 12
Since Laravel 11, the EventServiceProvider is gone. Laravel scans the Listeners directory and uses reflection to determine which events each listener responds to based on the type hint in the handle method signature.
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
class SendOrderConfirmation
{
public function handle(OrderShipped $event): void
{
// Send confirmation email to $event->order->user
}
}The listener above gets automatically registered for OrderShipped events. No manual binding in a service provider. This reduces boilerplate and keeps event-listener relationships close to the code that implements them.
To verify registered listeners, run php artisan event:list. For production, cache the event manifest with php artisan event:cache to skip directory scanning on each request.
Creating Events and Listeners with Artisan
Laravel provides Artisan commands to scaffold events and listeners:
# Generate an event class
php artisan make:event OrderShipped
# Generate a listener linked to an event
php artisan make:listener SendShipmentNotification --event=OrderShippedThe generated event class uses three traits: Dispatchable for the static dispatch() method, InteractsWithSockets for broadcasting, and SerializesModels to serialize Eloquent models when listeners are queued.
<?php
namespace App\Events;
use App\Models\Order;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Queue\SerializesModels;
class OrderShipped
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct(
public Order $order,
) {}
}The event class is a data container. It holds the Order model and nothing else. Business logic belongs in listeners, not events.
Dispatching Events from Controllers and Services
Dispatch events using the static dispatch() method on the event class:
<?php
namespace App\Http\Controllers;
use App\Events\OrderShipped;
use App\Models\Order;
use Illuminate\Http\Request;
class OrderController extends Controller
{
public function ship(Request $request, Order $order)
{
// Shipping logic here...
OrderShipped::dispatch($order);
return redirect()->route('orders.index');
}
}For conditional dispatch, use dispatchIf() or dispatchUnless():
// Only dispatch if the order has a tracking number
OrderShipped::dispatchIf($order->tracking_number !== null, $order);Ready to ace your Laravel interviews?
Practice with our interactive simulators, flashcards, and technical tests.
Queued Listeners for Slow Operations
Listeners that send emails, call external APIs, or perform heavy computations should run asynchronously. Implement ShouldQueue to push the listener onto the queue:
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
public $queue = 'notifications';
public $delay = 60; // Wait 60 seconds before processing
public function handle(OrderShipped $event): void
{
// Send notification to $event->order->user
}
}Customize queue connection and name with $connection and $queue properties, or use runtime methods:
public function viaConnection(): string
{
return 'redis';
}
public function viaQueue(): string
{
return $this->event->order->priority === 'high'
? 'high-priority'
: 'default';
}Conditional Queueing with shouldQueue
Sometimes a listener should only queue based on event data:
public function shouldQueue(OrderShipped $event): bool
{
// Only queue for orders above $100
return $event->order->total >= 10000;
}Database Transactions and Event Timing
Queued listeners dispatched inside a transaction may process before the transaction commits, causing missing data errors. Two solutions exist:
1. Configure globally in config/queue.php:
'connections' => [
'redis' => [
'after_commit' => true,
],
],2. Per-listener with ShouldQueueAfterCommit:
use Illuminate\Contracts\Queue\ShouldQueueAfterCommit;
class UpdateInventory implements ShouldQueueAfterCommit
{
public function handle(OrderShipped $event): void
{
// Safe to query the order, transaction is committed
}
}For events themselves, implement ShouldDispatchAfterCommit on the event class:
use Illuminate\Contracts\Events\ShouldDispatchAfterCommit;
class OrderShipped implements ShouldDispatchAfterCommit
{
// Event only dispatches after transaction commits
}Unique Listeners to Prevent Duplicates
The ShouldBeUnique interface prevents duplicate listeners from queueing while one is already processing:
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
class ProcessLicenseKey implements ShouldQueue, ShouldBeUnique
{
public $uniqueFor = 3600; // Lock expires after 1 hour
public function uniqueId(LicensePurchased $event): string
{
return 'license:' . $event->license->id;
}
public function handle(LicensePurchased $event): void
{
// Generate and assign license key
}
}If the same license ID triggers multiple events quickly, only the first listener processes. Subsequent attempts find the lock held and skip queueing.
Event Subscribers for Related Events
When multiple related events share common handling logic, event subscribers group handlers in a single class:
<?php
namespace App\Listeners;
use Illuminate\Auth\Events\Login;
use Illuminate\Auth\Events\Logout;
use Illuminate\Events\Dispatcher;
class UserActivitySubscriber
{
public function handleLogin(Login $event): void
{
// Log successful login, update last_login timestamp
}
public function handleLogout(Logout $event): void
{
// Log logout, clear session data
}
public function subscribe(Dispatcher $events): array
{
return [
Login::class => 'handleLogin',
Logout::class => 'handleLogout',
];
}
}Subscribers follow automatic discovery rules. If handler methods are in the subscriber class with properly type-hinted parameters, Laravel registers them automatically.
Listening to Multiple Events with Union Types
A single listener can respond to multiple event types using PHP 8 union types:
public function handle(OrderShipped|OrderCancelled $event): void
{
match (true) {
$event instanceof OrderShipped => $this->notifyShipped($event),
$event instanceof OrderCancelled => $this->notifyCancelled($event),
};
}This pattern works well for notifications that follow similar logic across different event types.
Deferring Events with Event::defer
Laravel 12 introduced Event::defer() to delay event dispatch until after a code block completes. This ensures listeners have access to all related records:
use Illuminate\Support\Facades\Event;
Event::defer(function () {
$user = User::create(['name' => 'John']);
$user->posts()->create(['title' => 'Welcome']);
});
// Events for both User and Post creation dispatch hereIf an exception occurs inside the closure, deferred events never dispatch.
Start practicing!
Test your knowledge with our interview simulators and technical tests.
Interview Questions on Laravel Events and Listeners
Technical interviews frequently test understanding of event-driven architecture. Here are questions that distinguish experienced Laravel developers:
Q: How does Laravel 12 register event listeners without EventServiceProvider?
Laravel scans app/Listeners using reflection. It reads the type hint on handle() or __invoke() methods to determine which event each listener responds to. Cache the manifest in production with php artisan event:cache.
Q: When should a listener implement ShouldQueue?
Whenever the operation takes more than a few milliseconds: sending emails, calling external APIs, generating reports, or processing files. Synchronous listeners block the HTTP response.
Q: What problem does ShouldQueueAfterCommit solve?
Queued listeners may process before the database transaction commits. If the listener queries for a just-created record, it fails because the data is not yet committed. ShouldQueueAfterCommit delays queue dispatch until the transaction completes.
Q: How do you prevent duplicate processing for the same event?
Implement ShouldBeUnique. Define uniqueId() to return a cache key based on event data. The listener acquires an atomic lock, and duplicate dispatches skip if the lock is held.
Q: What is the difference between an event listener and an event subscriber?
A listener handles one event type. A subscriber is a class that registers handlers for multiple related events in a single place, useful for grouping authentication events or audit logging.
What Laravel Events Mean for Scalable Applications
- Events decouple components, letting features like notifications and analytics evolve independently
- Queued listeners offload slow operations, keeping HTTP responses fast
ShouldQueueAfterCommitprevents race conditions between queue workers and database transactions- Automatic discovery in Laravel 12 removes configuration overhead, keeping listener logic close to implementation
- Event subscribers consolidate related event handling, reducing file sprawl for common patterns like user activity tracking
- The
/technologies/laravel/interview-questions/events-listenersmodule on SharpSkill covers these patterns with interactive questions
Can you spot the bug in Laravel?
One real snippet, one hidden bug, one attempt a day. No account needed to try.

Written by
Anthony Fillion-MailletFounder of SharpSkill
Full-stack developer for over 10 years. Runs SharpSkill and answers for everything published here.
Updated on August 20, 2026
Tags
Share
Related articles

PHP Laravel Framework Interview Questions 2026: Eloquent, Queues and Architecture Patterns
Master Laravel 13 interview questions covering Eloquent ORM relationships, queue architecture, service container patterns, and real-world coding challenges that senior developers face in 2026.

Laravel Queues and Jobs: Asynchronous Architecture and Interview Questions 2026
Deep dive into Laravel queues and jobs architecture. Covers job dispatching, batching, chaining, middleware, failed job handling, and queue worker management with Laravel 12 examples.

PHP Laravel Developer Interview Questions 2026: Complete Preparation Guide
Master Laravel interview questions for 2026. From Eloquent ORM and Service Container to queues, testing, and Laravel 13 features, prepare for technical interviews with real-world examples.