¿Qué es broadcasting?
Con WebSocket puedes enviar datos en tiempo real del servidor al cliente.
El broadcasting de Laravel es el mecanismo para hacer llegar eventos del lado del servidor al JavaScript del frontend mediante WebSocket.
Por ejemplo, cuando cambia el estado de un pedido, la actualización se muestra al instante en el navegador sin recargar la página.
La gran ventaja del broadcasting de Laravel es que compartes tal cual el nombre del evento y sus datos entre servidor y cliente.
El broadcasting se construye sobre el sistema de eventos de Laravel.
Se recomienda entender primero eventos y listeners.
Configuración
En una aplicación nueva el broadcasting está deshabilitado por defecto.
Actívalo con el comando Artisan install:broadcasting.
php artisan install:broadcasting
El comando te pedirá que elijas el servicio de broadcasting y generará config/broadcasting.php y routes/channels.php.
Laravel Reverb
Desde Laravel 11 se recomienda usar Laravel Reverb, el servidor WebSocket oficial.
Reverb es auto-hospedado y permite tiempo real sin depender de servicios externos.
Instalación
Con la opción --reverb, install:broadcasting instala los paquetes de Composer y NPM que necesita Reverb y configura .env de una sola vez.
php artisan install:broadcasting --reverb
Si prefieres instalarlo manualmente, añade el paquete con Composer y luego ejecuta el comando de instalación.
composer require laravel/reverb
php artisan reverb:install
Valores clave en .env
BROADCAST_CONNECTION=reverb
REVERB_APP_ID=my-app-id
REVERB_APP_KEY=my-app-key
REVERB_APP_SECRET=my-app-secret
REVERB_HOST=localhost
REVERB_PORT=8080
REVERB_SCHEME=http
VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
VITE_REVERB_HOST="${REVERB_HOST}"
VITE_REVERB_PORT="${REVERB_PORT}"
VITE_REVERB_SCHEME="${REVERB_SCHEME}"
Arrancar el servidor Reverb
En producción, gestiónalo como daemon con un gestor de procesos como Supervisor.
Los eventos de broadcast se procesan a través de la cola.
Debes arrancar también un worker de cola aparte del servidor Reverb.
Crear eventos de broadcast
Generar la clase del evento
php artisan make:event OrderShipmentStatusUpdated
En la clase generada, implementa la interfaz ShouldBroadcast.
<?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\Queue\SerializesModels;
class OrderShipmentStatusUpdated implements ShouldBroadcast
{
use InteractsWithSockets, SerializesModels;
public function __construct(
public Order $order,
) {}
/**
* Devuelve el canal al que se emite el evento
*/
public function broadcastOn(): Channel
{
return new PrivateChannel('orders.' . $this->order->id);
}
}
Con solo implementar ShouldBroadcast, cuando se despacha el evento se emite automáticamente a través de la cola.
Personalizar los datos emitidos
Por defecto, todas las propiedades public de la clase se incluyen en el payload.
Para limitar los datos, define broadcastWith.
public function broadcastWith(): array
{
return [
'order_id' => $this->order->id,
'status' => $this->order->status,
];
}
Personalizar el nombre del evento
Por defecto se usa el nombre de la clase.
Cámbialo con broadcastAs.
public function broadcastAs(): string
{
return 'order.status.updated';
}
Al escuchar en el frontend, antepón un . para desactivar el prefijo del namespace de la aplicación.
Echo.private(`orders.${orderId}`)
.listen('.order.status.updated', (e) => {
console.log(e);
});
Tipos de canal
| Canal | Clase | Descripción |
|---|
| Public | Channel | No requiere autenticación. Cualquiera puede suscribirse |
| Private | PrivateChannel | Solo usuarios autenticados. Requiere lógica de autorización |
| Presence | PresenceChannel | Extensión de Private. Puedes conocer los miembros del canal |
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
// Canal público
public function broadcastOn(): Channel
{
return new Channel('posts');
}
// Canal privado
public function broadcastOn(): Channel
{
return new PrivateChannel('orders.' . $this->order->id);
}
// Canal presence
public function broadcastOn(): Channel
{
return new PresenceChannel('rooms.' . $this->room->id);
}
Para emitir a varios canales, devuelve un array.
public function broadcastOn(): array
{
return [
new PrivateChannel('orders.' . $this->order->id),
new Channel('admin.orders'),
];
}
Autorización de canales
Los canales Private y Presence se verifican en el servidor antes de que el cliente pueda suscribirse.
routes/channels.php
Define los callbacks de autorización en routes/channels.php, generado por install:broadcasting.
use App\Models\Order;
use App\Models\User;
use Illuminate\Support\Facades\Broadcast;
Broadcast::channel('orders.{orderId}', function (User $user, int $orderId) {
return $user->id === Order::findOrNew($orderId)->user_id;
});
El primer argumento del callback es el usuario autenticado; los demás son los comodines del nombre del canal.
Devuelve true o un valor truthy para autorizar, o false para denegar.
También se puede usar route model binding.
Con el nombre orders.{order} se recibe una instancia del modelo Order.
Broadcast::channel('orders.{order}', function (User $user, Order $order) {
return $user->id === $order->user_id;
});
Cuando hay muchos canales puedes organizarlos con clases dedicadas.
php artisan make:channel OrderChannel
<?php
namespace App\Broadcasting;
use App\Models\Order;
use App\Models\User;
class OrderChannel
{
public function join(User $user, Order $order): bool
{
return $user->id === $order->user_id;
}
}
Regístrala en routes/channels.php.
use App\Broadcasting\OrderChannel;
Broadcast::channel('orders.{order}', OrderChannel::class);
Emisión del evento
Los eventos que implementan ShouldBroadcast se disparan como cualquier otro.
use App\Events\OrderShipmentStatusUpdated;
OrderShipmentStatusUpdated::dispatch($order);
Para emitir solo a los demás usuarios excluyendo el emisor, usa toOthers.
broadcast(new OrderShipmentStatusUpdated($order))->toOthers();
Para usar toOthers, la clase del evento debe usar el trait InteractsWithSockets.
Recepción en el frontend
Configuración de Laravel Echo
Con Reverb, configura una instancia de Echo en resources/js/bootstrap.js.
npm install --save-dev laravel-echo pusher-js
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
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 ?? 80,
wssPort: import.meta.env.VITE_REVERB_PORT ?? 443,
forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
enabledTransports: ['ws', 'wss'],
});
Escuchar eventos
// Canal público
Echo.channel('posts')
.listen('PostPublished', (e) => {
console.log(e.post);
});
// Canal privado
Echo.private(`orders.${orderId}`)
.listen('OrderShipmentStatusUpdated', (e) => {
console.log(e.order);
});
// Canal presence
Echo.join(`rooms.${roomId}`)
.here((users) => {
console.log('Miembros actuales:', users);
})
.joining((user) => {
console.log(user.name, 'se ha unido');
})
.leaving((user) => {
console.log(user.name, 'ha salido');
})
.listen('MessagePosted', (e) => {
console.log(e.message);
});
Uso de hooks para React / Vue
Si usas starter kits de React o Vue, los hooks dedicados simplifican el código.
import { useEcho } from "@laravel/echo-react";
// Canal privado
useEcho(
`orders.${orderId}`,
"OrderShipmentStatusUpdated",
(e) => {
console.log(e.order);
},
);
// Canal público
import { useEchoPublic } from "@laravel/echo-react";
useEchoPublic("posts", "PostPublished", (e) => {
console.log(e.post);
});
El hook useEcho deja automáticamente el canal al desmontar el componente.
Antes de compilar los assets del frontend, comprueba que las variables VITE_REVERB_* de .env estén bien configuradas.
Ejemplo práctico: actualización en tiempo real del estado del pedido
Activar broadcasting
php artisan install:broadcasting --reverb
Arranca el servidor Reverb y el worker de cola.php artisan reverb:start
php artisan queue:work
Crear la clase del evento
php artisan make:event OrderShipmentStatusUpdated
Edita app/Events/OrderShipmentStatusUpdated.php.<?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\Queue\SerializesModels;
class OrderShipmentStatusUpdated implements ShouldBroadcast
{
use InteractsWithSockets, SerializesModels;
public function __construct(
public Order $order,
) {}
public function broadcastOn(): Channel
{
return new PrivateChannel('orders.' . $this->order->id);
}
public function broadcastWith(): array
{
return [
'order_id' => $this->order->id,
'status' => $this->order->status,
];
}
}
Definir la autorización del canal
Añade la lógica en routes/channels.php.use App\Models\Order;
use App\Models\User;
use Illuminate\Support\Facades\Broadcast;
Broadcast::channel('orders.{order}', function (User $user, Order $order) {
return $user->id === $order->user_id;
});
Disparar el evento
Dispáralo en el controlador o job que actualiza el estado del pedido.use App\Events\OrderShipmentStatusUpdated;
$order->update(['status' => 'shipped']);
OrderShipmentStatusUpdated::dispatch($order);
Escuchar en el frontend
Escucha con script inline en Blade o desde un componente React/Vue.Echo.private(`orders.${orderId}`)
.listen('OrderShipmentStatusUpdated', (e) => {
document.getElementById('status').textContent = e.status;
});
Próximos pasos
Laravel Reverb
Consulta los detalles de configuración, operación en producción y escalado del servidor Reverb.
Colas y jobs
El broadcasting se procesa a través de la cola. Revisa la configuración y operación de las colas.
Eventos y listeners
Aprende los detalles del sistema de eventos de Laravel, la base del broadcasting.