Laravel Events e Listeners 2026: Architettura Event-Driven e Domande da Colloquio
Guida completa a Laravel Events e Listeners nel 2026. Architettura Event-Driven, Observer Pattern, Broadcasting e le domande più frequenti nei colloqui tecnici con esempi di codice.

Il sistema di eventi di Laravel rappresenta un pilastro fondamentale per costruire applicazioni scalabili e manutenibili. In un contesto dove microservizi e elaborazione asincrona sono diventati lo standard, Events e Listeners permettono una comunicazione flessibile e disaccoppiata tra le diverse componenti di un'applicazione. Laravel 12 ha raffinato ulteriormente questo sistema, introducendo typed Events, Broadcasting migliorato e integrazione nativa con le Queue. Questo articolo esplora i fondamenti degli eventi Laravel, pattern avanzati e le domande più comuni nei colloqui tecnici.
L'Observer Pattern, alla base del sistema di eventi Laravel, permette di reagire ad azioni senza modificare direttamente il codice che le genera. Quando un utente si registra, un evento può essere emesso e molteplici Listener possono reagire: invio email, tracciamento analytics, sincronizzazione CRM. Il codice di registrazione rimane snello e focalizzato sulla sua responsabilità principale.
Creazione di Events e Listeners
Laravel fornisce comandi Artisan per generare rapidamente Events e Listeners. Un Event rappresenta un'azione avvenuta nell'applicazione, mentre un Listener reagisce a quell'evento eseguendo operazioni specifiche.
php artisan make:event OrderPlaced
php artisan make:listener SendOrderConfirmation --event=OrderPlaced
php artisan make:listener UpdateInventory --event=OrderPlaced
php artisan make:listener NotifyWarehouse --event=OrderPlacedLa classe Event contiene i dati rilevanti che vengono passati a tutti i Listeners. Laravel 12 supporta typed properties e Constructor Property Promotion per un codice più conciso.
<?php
namespace App\Events;
use App\Models\Order;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class OrderPlaced
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct(
public Order $order,
public float $totalAmount,
public string $currency = 'EUR'
) {}
}Il Listener associato implementa il metodo handle, che riceve l'evento come parametro. La dichiarazione dei tipi abilita l'autocompletamento IDE e l'analisi statica.
<?php
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->email)
->queue(new OrderConfirmation($event->order));
}
}Registrazione Eventi e Auto-Discovery
Laravel 12 offre due metodi per registrare gli eventi: registrazione esplicita nell'EventServiceProvider e discovery automatica. Il metodo esplicito offre maggiore controllo e chiarezza.
<?php
namespace App\Providers;
use App\Events\OrderPlaced;
use App\Events\PaymentProcessed;
use App\Listeners\NotifyWarehouse;
use App\Listeners\SendOrderConfirmation;
use App\Listeners\UpdateInventory;
use App\Listeners\SendPaymentReceipt;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
protected $listen = [
OrderPlaced::class => [
SendOrderConfirmation::class,
UpdateInventory::class,
NotifyWarehouse::class,
],
PaymentProcessed::class => [
SendPaymentReceipt::class,
],
];
public function shouldDiscoverEvents(): bool
{
return false; // Registrazione esplicita preferita
}
}Per la discovery automatica, Laravel analizza le classi Listener e determina a quali eventi rispondono basandosi sulla firma del metodo handle. Questo approccio è adatto per progetti piccoli o prototipazione rapida.
public function shouldDiscoverEvents(): bool
{
return true;
}
protected function discoverEventsWithin(): array
{
return [
$this->app->path('Listeners'),
$this->app->path('Modules/Orders/Listeners'),
];
}Queued Listeners per Elaborazione Asincrona
Operazioni che richiedono tempo come l'invio di email o chiamate ad API esterne non dovrebbero essere elaborate in modo sincrono. Implementando l'interfaccia ShouldQueue, i Listeners vengono automaticamente accodati.
<?php
namespace App\Listeners;
use App\Events\OrderPlaced;
use App\Services\InventoryService;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class UpdateInventory implements ShouldQueue
{
use InteractsWithQueue;
public string $queue = 'inventory';
public int $tries = 3;
public int $backoff = 60;
public function __construct(
private InventoryService $inventoryService
) {}
public function handle(OrderPlaced $event): void
{
foreach ($event->order->items as $item) {
$this->inventoryService->decrementStock(
$item->product_id,
$item->quantity
);
}
}
public function failed(OrderPlaced $event, \Throwable $exception): void
{
// Log errore, notifica admin, azione compensativa
logger()->error('Aggiornamento inventario fallito', [
'order_id' => $event->order->id,
'error' => $exception->getMessage(),
]);
}
}La configurazione di queue, tentativi di retry e tempo di backoff permette una gestione robusta degli errori. Il metodo failed viene invocato quando tutti i tentativi sono esauriti.
Model Events e Observers
I modelli Eloquent emettono automaticamente eventi durante le operazioni CRUD. Questi Model Events permettono di reagire alle modifiche del database senza alterare il codice dei controller.
<?php
namespace App\Models;
use App\Events\OrderPlaced;
use App\Observers\OrderObserver;
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
use Illuminate\Database\Eloquent\Model;
#[ObservedBy(OrderObserver::class)]
class Order extends Model
{
protected $dispatchesEvents = [
'created' => OrderPlaced::class,
];
}Le classi Observer raggruppano tutti gli handler di eventi per un Model in un unico punto centrale. Laravel 12 supporta l'attributo ObservedBy per una registrazione dichiarativa.
<?php
namespace App\Observers;
use App\Models\Order;
use App\Services\AuditLogService;
class OrderObserver
{
public function __construct(
private AuditLogService $auditLog
) {}
public function creating(Order $order): void
{
$order->order_number = $this->generateOrderNumber();
}
public function created(Order $order): void
{
$this->auditLog->log('order.created', $order);
}
public function updating(Order $order): void
{
if ($order->isDirty('status')) {
$order->status_changed_at = now();
}
}
public function deleted(Order $order): void
{
$this->auditLog->log('order.deleted', $order);
}
private function generateOrderNumber(): string
{
return 'ORD-' . date('Ymd') . '-' . strtoupper(uniqid());
}
}Event Broadcasting per Aggiornamenti Real-Time
Laravel Broadcasting permette di trasmettere eventi server-side ai client frontend tramite WebSocket. Questo è essenziale per dashboard in tempo reale, applicazioni chat e notifiche live.
<?php
namespace App\Events;
use App\Models\Order;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class OrderStatusUpdated implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public function __construct(
public Order $order,
public string $previousStatus,
public string $newStatus
) {}
public function broadcastOn(): array
{
return [
new PrivateChannel('orders.' . $this->order->user_id),
new Channel('admin.orders'),
];
}
public function broadcastAs(): string
{
return 'order.status.updated';
}
public function broadcastWith(): array
{
return [
'order_id' => $this->order->id,
'order_number' => $this->order->order_number,
'previous_status' => $this->previousStatus,
'new_status' => $this->newStatus,
'updated_at' => now()->toISOString(),
];
}
}Il frontend può ricevere questi eventi con Laravel Echo e aggiornare l'interfaccia utente di conseguenza.
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Echo = new Echo({
broadcaster: 'reverb',
key: import.meta.env.VITE_REVERB_APP_KEY,
wsHost: import.meta.env.VITE_REVERB_HOST,
wsPort: import.meta.env.VITE_REVERB_PORT,
forceTLS: true,
});
Echo.private(`orders.${userId}`)
.listen('.order.status.updated', (event) => {
console.log('Stato ordine cambiato:', event);
updateOrderStatus(event.order_id, event.new_status);
});Event Subscribers per Workflow Complessi
Gli Event Subscribers permettono di raggruppare più handler di eventi in una singola classe. Questo è utile per logica specifica di dominio che deve reagire a diversi eventi.
<?php
namespace App\Listeners;
use App\Events\OrderPlaced;
use App\Events\OrderShipped;
use App\Events\OrderDelivered;
use App\Events\OrderCancelled;
use App\Services\NotificationService;
use Illuminate\Events\Dispatcher;
class OrderEventSubscriber
{
public function __construct(
private NotificationService $notifications
) {}
public function handleOrderPlaced(OrderPlaced $event): void
{
$this->notifications->sendOrderConfirmation($event->order);
}
public function handleOrderShipped(OrderShipped $event): void
{
$this->notifications->sendShippingNotification(
$event->order,
$event->trackingNumber
);
}
public function handleOrderDelivered(OrderDelivered $event): void
{
$this->notifications->sendDeliveryConfirmation($event->order);
$this->notifications->requestReview($event->order);
}
public function handleOrderCancelled(OrderCancelled $event): void
{
$this->notifications->sendCancellationNotification(
$event->order,
$event->reason
);
}
public function subscribe(Dispatcher $events): array
{
return [
OrderPlaced::class => 'handleOrderPlaced',
OrderShipped::class => 'handleOrderShipped',
OrderDelivered::class => 'handleOrderDelivered',
OrderCancelled::class => 'handleOrderCancelled',
];
}
}Il Subscriber viene registrato nell'EventServiceProvider e raggruppa logicamente tutti gli handler correlati.
protected $subscribe = [
OrderEventSubscriber::class,
PaymentEventSubscriber::class,
];Pronto a superare i tuoi colloqui su Laravel?
Pratica con i nostri simulatori interattivi, flashcards e test tecnici.
Domande da Colloquio su Laravel Events
Domanda: Qual è la differenza tra Events e Observers in Laravel?
Gli Events sono messaggi generici che possono essere emessi ovunque nell'applicazione ed elaborati da qualsiasi Listener. Gli Observers sono progettati specificamente per i modelli Eloquent e reagiscono automaticamente alle operazioni CRUD. Gli Events offrono maggiore flessibilità, mentre gli Observers sono ottimizzati per logica specifica dei Model.
Domanda: Come si impedisce a un Listener di bloccare la propagazione degli eventi?
Se un Listener restituisce false, i Listeners successivi non vengono eseguiti. Per evitare questo comportamento, i Listeners dovrebbero restituire void o un altro valore. L'ordine dei Listeners nell'array determina l'ordine di esecuzione.
Domanda: Quando si dovrebbe usare ShouldBeUnique con Queued Listeners?
ShouldBeUnique impedisce che lo stesso job venga inserito più volte nella coda. Questo è importante per operazioni idempotenti come l'invio di email, dove i duplicati devono essere evitati.
class SendWelcomeEmail implements ShouldQueue, ShouldBeUnique
{
public function uniqueId(): string
{
return $this->user->id;
}
}Domanda: Come si testa la logica basata su eventi?
Laravel fornisce Event::fake() per test isolati. Questo impedisce l'effettivo dispatch degli eventi e permette di effettuare assertions.
public function test_order_placement_dispatches_event(): void
{
Event::fake([OrderPlaced::class]);
$order = Order::factory()->create();
Event::assertDispatched(OrderPlaced::class, function ($event) use ($order) {
return $event->order->id === $order->id;
});
}Conclusione
Laravel Events e Listeners costituiscono un sistema potente per architetture applicative disaccoppiate e manutenibili. La combinazione di eventi sincroni, Queued Listeners e Broadcasting permette sia notifiche semplici che architetture Event-Driven complesse. I Model Observers semplificano la reazione alle modifiche del database, mentre gli Event Subscribers raggruppano handler correlati. Per i colloqui tecnici, una comprensione approfondita di questi concetti è essenziale, poiché l'architettura Event-Driven è diventata lo standard nelle applicazioni Laravel moderne.
Sapresti trovare il bug in Laravel?
Uno snippet reale, un bug nascosto, un tentativo al giorno. Senza account per provare.

Scritto da
Anthony Fillion-MailletFondatore di SharpSkill
Sviluppatore fullstack da oltre 10 anni. Guida SharpSkill e risponde di tutto ciò che vi viene pubblicato.
Aggiornato il 20 agosto 2026
Tag
Condividi
Articoli correlati

Laravel 12 nel 2026: Nuove Funzionalità, Starter Kit e Domande per Colloqui
Laravel 12 introduce Starter Kit completamente riprogettati con React 19, Vue 3, Livewire 4 e WorkOS AuthKit. Una guida completa alle nuove funzionalità, al percorso di aggiornamento e alle domande chiave per i colloqui tecnici del 2026.

Laravel Solutions: Pattern Avanzati, Debugging e Domande da Colloquio 2026
Padroneggia le soluzioni Laravel con pattern architetturali avanzati, tecniche di debugging e preparazione ai colloqui. Service class, repository pattern, debugging con Telescope e domande frequenti per sviluppatori Laravel.

Laravel Testing con Pest 5 nel 2026: TIA, Mocking e Domande da Colloquio
Best practice per il testing Laravel con Pest 5, Test Impact Analysis, Mockery, facade fake e test architetturali. Unit test, feature test, strategie di mocking e domande frequenti nei colloqui per sviluppatori Laravel.