Capítulo 18: Comunicação em Tempo Real com WebSockets (Laravel Reverb)
Especialização em Backend com PHP & Laravel • Laravel 11 & PHP 8.3+ • Eloquent ORM, Sanctum, Filas, Horizon e APIs Corporativas
🗺️ Mapa Conceitual do Tópico
flowchart TD
A["Ação no Backend (ex: Pedido atualizado)"] --> B["Event implements ShouldBroadcast"]
B --> C["Fila de Broadcast"]
C --> D["Servidor Reverb (WebSocket)"]
D --> E["Laravel Echo no Cliente"]
subgraph AUTH["Autorização de Canal"]
F["routes/channels.php"]
end
D -.-> AUTH
E --> G["UI atualizada em tempo real"]
style A fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px
style B fill:#e8f5e9,stroke:#4caf50,stroke-width:2px
style C fill:#fff3e0,stroke:#ff9800,stroke-width:2px
style D fill:#ede7f6,stroke:#7e57c2,stroke-width:2px
style E fill:#fce4ec,stroke:#e91e63,stroke-width:2px
style F fill:#f3e5f5,stroke:#9c27b0,stroke-width:2px
🏛️ 1. Do Polling ao WebSocket: Por que Broadcasting
Antes do broadcasting, a única forma de o frontend “saber” que algo mudou no backend era fazer polling — requisições HTTP repetidas em intervalo fixo, desperdiçando banda e adicionando latência perceptível. O Laravel Reverb é o servidor de WebSockets oficial do ecossistema, escrito em PHP assíncrono, que mantém conexões abertas e permite o backend empurrar (push) eventos para o cliente no instante em que ocorrem — sem depender de serviços pagos de terceiros como Pusher.
O fluxo é sempre o mesmo: um Evento de domínio implementa ShouldBroadcast, é despachado para a fila (broadcasting é assíncrono por padrão), e o worker publica a mensagem no canal correspondente do Reverb, que a repassa a todos os clientes conectados via Laravel Echo.
<?php
namespace App\Events;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Queue\SerializesModels;
use App\Models\Pedido;
class StatusPedidoAtualizadoEvent implements ShouldBroadcast
{
use SerializesModels;
public function __construct(public Pedido $pedido) {}
public function broadcastOn(): array
{
return [new PrivateChannel('pedidos.' . $this->pedido->user_id)];
}
public function broadcastAs(): string
{
return 'status.atualizado';
}
}
🔒 2. Tipos de Canal e Autorização
Existem três tipos de canal: público (Channel, sem autenticação, qualquer um escuta), privado (PrivateChannel, exige que o usuário autenticado seja autorizado) e de presença (PresenceChannel, privado + lista de quem está online). A autorização de canais privados e de presença é declarada em routes/channels.php e roda a cada tentativa de conexão do cliente àquele canal:
<?php
use Illuminate\Support\Facades\Broadcast;
// Canal privado: só o dono do pedido pode escutar suas atualizações.
Broadcast::channel('pedidos.{userId}', function ($user, $userId) {
return (int) $user->id === (int) $userId;
});
// Canal de presença: retorna os dados do usuário que ficam visíveis a todos os presentes.
Broadcast::channel('chat.{salaId}', function ($user, $salaId) {
return ['id' => $user->id, 'name' => $user->name];
});
Se o callback retornar false ou null, o Reverb recusa a conexão com HTTP 403 — isso é essencial, pois um canal privado mal configurado pode vazar dados de um usuário para outro.
⚙️ 3. Configurando e Subindo o Servidor Reverb
// config/reverb.php
return [
'servers' => [
'reverb' => [
'host' => env('REVERB_SERVER_HOST', '0.0.0.0'),
'port' => env('REVERB_SERVER_PORT', 8080),
'hostname' => env('REVERB_HOST'),
],
],
];
php artisan reverb:start --debug
O Reverb é um processo de longa duração (não um request PHP-FPM tradicional), projetado para lidar com dezenas de milhares de conexões simultâneas usando um loop de eventos assíncrono. Em produção, ele roda atrás de um proxy reverso (Nginx/Caddy) com suporte a upgrade de protocolo HTTP → WebSocket, e normalmente é supervisionado por um processo como o Supervisor ou Horizon (para a fila de broadcast).
Gotcha comum: esquecer que o broadcast por padrão é assíncrono — se QUEUE_CONNECTION não estiver configurada corretamente ou nenhum worker estiver rodando (php artisan queue:work), os eventos ficam presos na fila e nunca chegam ao cliente, mesmo que o código pareça correto.