Eventos e Listeners no Laravel 2026: Arquitetura Event-Driven e Perguntas de Entrevista
Domine eventos e listeners do Laravel com a descoberta automática do Laravel 12, listeners assíncronos e padrões de arquitetura event-driven para entrevistas técnicas.

Eventos e listeners do Laravel implementam o padrão Observer, desacoplando componentes ao permitir que diferentes partes de uma aplicação reajam a ações sem dependências diretas. Quando um usuário realiza um pedido, o evento OrderShipped é disparado, e listeners separados tratam notificações, analytics e atualizações de inventário de forma independente.
O Laravel 12 descobre automaticamente os listeners em app/Listeners. Qualquer classe com um método handle ou __invoke que tenha type hint de um evento é registrada automaticamente, sem necessidade de arquivo de configuração.
Como Funciona a Descoberta de Eventos no Laravel 12
Desde o Laravel 11, o EventServiceProvider não existe mais. O Laravel escaneia o diretório Listeners e usa reflection para determinar quais eventos cada listener trata, baseando-se no type hint da assinatura do método handle.
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
class SendOrderConfirmation
{
public function handle(OrderShipped $event): void
{
// Enviar email de confirmação para $event->order->user
}
}O listener acima é automaticamente registrado para eventos OrderShipped. Não é necessário binding manual em um service provider. Essa abordagem reduz código repetitivo e mantém as relações evento-listener próximas do código que as implementa.
Para verificar os listeners registrados, executar php artisan event:list. Em produção, fazer cache do manifesto com php artisan event:cache para evitar o escaneamento do diretório em cada requisição.
Criação de Eventos e Listeners com Artisan
O Laravel fornece comandos Artisan para gerar eventos e listeners:
# Gerar uma classe de evento
php artisan make:event OrderShipped
# Gerar um listener vinculado a um evento
php artisan make:listener SendShipmentNotification --event=OrderShippedA classe de evento gerada usa três traits: Dispatchable para o método estático dispatch(), InteractsWithSockets para broadcasting, e SerializesModels para serializar models Eloquent quando os listeners estão na fila.
<?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,
) {}
}A classe de evento é um container de dados. Ela contém o model Order e nada mais. A lógica de negócio pertence aos listeners, não aos eventos.
Dispatch de Eventos a partir de Controllers e Services
Disparar eventos usando o método estático dispatch() na classe de evento:
<?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)
{
// Lógica de envio aqui...
OrderShipped::dispatch($order);
return redirect()->route('orders.index');
}
}Para dispatch condicional, usar dispatchIf() ou dispatchUnless():
// Disparar apenas se o pedido tiver número de rastreamento
OrderShipped::dispatchIf($order->tracking_number !== null, $order);Pronto para mandar bem nas entrevistas de Laravel?
Pratique com nossos simuladores interativos, flashcards e testes tecnicos.
Listeners Assíncronos para Operações Lentas
Listeners que enviam emails, chamam APIs externas ou realizam cálculos pesados devem executar de forma assíncrona. Implementar ShouldQueue para colocar o listener na fila:
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
public $queue = 'notifications';
public $delay = 60; // Aguardar 60 segundos antes de processar
public function handle(OrderShipped $event): void
{
// Enviar notificação para $event->order->user
}
}Personalizar a conexão e nome da fila com as propriedades $connection e $queue, ou usar métodos dinâmicos:
public function viaConnection(): string
{
return 'redis';
}
public function viaQueue(): string
{
return $this->event->order->priority === 'high'
? 'high-priority'
: 'default';
}Fila Condicional com shouldQueue
Às vezes um listener só deve ser enfileirado com base nos dados do evento:
public function shouldQueue(OrderShipped $event): bool
{
// Enfileirar apenas para pedidos acima de R$100
return $event->order->total >= 10000;
}Transações de Banco de Dados e Timing de Eventos
Listeners na fila despachados dentro de uma transação podem ser processados antes do commit da transação, causando erros de dados ausentes. Existem duas soluções:
1. Configuração global em config/queue.php:
'connections' => [
'redis' => [
'after_commit' => true,
],
],2. Por listener com ShouldQueueAfterCommit:
use Illuminate\Contracts\Queue\ShouldQueueAfterCommit;
class UpdateInventory implements ShouldQueueAfterCommit
{
public function handle(OrderShipped $event): void
{
// Seguro para consultar o pedido, transação commitada
}
}Para os próprios eventos, implementar ShouldDispatchAfterCommit na classe de evento:
use Illuminate\Contracts\Events\ShouldDispatchAfterCommit;
class OrderShipped implements ShouldDispatchAfterCommit
{
// O evento só é despachado após o commit da transação
}Listeners Únicos para Evitar Duplicatas
A interface ShouldBeUnique impede que listeners duplicados sejam enfileirados enquanto outro está processando:
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
class ProcessLicenseKey implements ShouldQueue, ShouldBeUnique
{
public $uniqueFor = 3600; // O lock expira após 1 hora
public function uniqueId(LicensePurchased $event): string
{
return 'license:' . $event->license->id;
}
public function handle(LicensePurchased $event): void
{
// Gerar e atribuir chave de licença
}
}Se o mesmo ID de licença dispara múltiplos eventos rapidamente, apenas o primeiro listener processa. Tentativas subsequentes encontram o lock ativo e pulam o enfileiramento.
Event Subscribers para Eventos Relacionados
Quando múltiplos eventos relacionados compartilham lógica de tratamento comum, os event subscribers agrupam handlers em uma única classe:
<?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
{
// Registrar login bem-sucedido, atualizar last_login
}
public function handleLogout(Logout $event): void
{
// Registrar logout, limpar dados de sessão
}
public function subscribe(Dispatcher $events): array
{
return [
Login::class => 'handleLogin',
Logout::class => 'handleLogout',
];
}
}Os subscribers seguem as regras de descoberta automática. Se os métodos handler estão na classe subscriber com parâmetros corretamente tipados, o Laravel os registra automaticamente.
Ouvir Múltiplos Eventos com Union Types
Um único listener pode responder a múltiplos tipos de eventos usando union types do PHP 8:
public function handle(OrderShipped|OrderCancelled $event): void
{
match (true) {
$event instanceof OrderShipped => $this->notifyShipped($event),
$event instanceof OrderCancelled => $this->notifyCancelled($event),
};
}Esse padrão funciona bem para notificações que seguem lógica similar entre diferentes tipos de eventos.
Adiar Eventos com Event::defer
O Laravel 12 introduziu Event::defer() para atrasar o dispatch de eventos até que um bloco de código complete. Isso garante que os listeners tenham acesso a todos os registros relacionados:
use Illuminate\Support\Facades\Event;
Event::defer(function () {
$user = User::create(['name' => 'John']);
$user->posts()->create(['title' => 'Welcome']);
});
// Os eventos para User e Post são despachados aquiSe uma exceção ocorre dentro da closure, os eventos adiados nunca são despachados.
Comece a praticar!
Teste seus conhecimentos com nossos simuladores de entrevista e testes tecnicos.
Perguntas de Entrevista sobre Eventos e Listeners do Laravel
Entrevistas técnicas frequentemente avaliam a compreensão de arquitetura event-driven. Estas são perguntas que distinguem desenvolvedores Laravel experientes:
P: Como o Laravel 12 registra event listeners sem EventServiceProvider?
O Laravel escaneia app/Listeners usando reflection. Ele lê o type hint nos métodos handle() ou __invoke() para determinar a qual evento cada listener responde. Fazer cache do manifesto em produção com php artisan event:cache.
P: Quando um listener deve implementar ShouldQueue?
Quando a operação leva mais do que alguns milissegundos: envio de emails, chamadas a APIs externas, geração de relatórios, ou processamento de arquivos. Listeners síncronos bloqueiam a resposta HTTP.
P: Qual problema o ShouldQueueAfterCommit resolve?
Listeners na fila podem ser processados antes do commit da transação do banco de dados. Se o listener consulta um registro recém-criado, ele falha porque os dados ainda não foram commitados. ShouldQueueAfterCommit atrasa o dispatch até que a transação complete.
P: Como evitar processamento duplicado para o mesmo evento?
Implementar ShouldBeUnique. Definir uniqueId() para retornar uma chave de cache baseada nos dados do evento. O listener adquire um lock atômico, e dispatches duplicados são pulados se o lock está ativo.
P: Qual é a diferença entre um event listener e um event subscriber?
Um listener trata um tipo de evento. Um subscriber é uma classe que registra handlers para múltiplos eventos relacionados em um único lugar, útil para agrupar eventos de autenticação ou registro de auditoria.
O Que os Eventos do Laravel Significam para Aplicações Escaláveis
- Eventos desacoplam componentes, permitindo que funcionalidades como notificações e analytics evoluam independentemente
- Listeners na fila descarregam operações lentas, mantendo as respostas HTTP rápidas
ShouldQueueAfterCommitprevine condições de corrida entre workers da fila e transações de banco de dados- A descoberta automática no Laravel 12 elimina a sobrecarga de configuração, mantendo a lógica dos listeners próxima da implementação
- Event subscribers consolidam o tratamento de eventos relacionados, reduzindo a dispersão de arquivos para padrões comuns como rastreamento de atividade do usuário
- O módulo
/technologies/laravel/interview-questions/events-listenersno SharpSkill cobre esses padrões com perguntas interativas
Você saberia encontrar o bug em Laravel?
Um trecho real, um bug escondido, uma tentativa por dia. Sem conta para testar.

Escrito por
Anthony Fillion-MailletFundador da SharpSkill
Desenvolvedor fullstack há mais de 10 anos. Dirige a SharpSkill e responde por tudo o que é publicado aqui.
Atualizado em 20 de agosto de 2026
Tags
Compartilhar
Artigos relacionados

Perguntas de Entrevista Laravel 2026: Eloquent, Queues e Padrões de Arquitetura
Guia completo de perguntas técnicas para entrevistas Laravel em 2026. Domine Eloquent ORM, queues, padrões de arquitetura e melhores práticas para sua próxima entrevista de emprego.

Laravel Queues e Jobs: Arquitetura Assíncrona e Perguntas de Entrevista 2026
Guia completo sobre filas e jobs no Laravel cobrindo batching, chaining, rate limiting, backoff exponencial e perguntas frequentes em entrevistas para desenvolvedores sênior.

Soluções Laravel: Padrões Avançados, Depuração e Perguntas de Entrevista 2026
Dominar soluções Laravel com padrões arquiteturais avançados, técnicas de depuração e conhecimentos essenciais para entrevistas. Classes de serviço, padrão Repository, depuração com Telescope e perguntas frequentes.