Saltar al contenido principal

¿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

php artisan reverb:start
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.
php artisan queue:work

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

CanalClaseDescripción
PublicChannelNo requiere autenticación. Cualquiera puede suscribirse
PrivatePrivateChannelSolo usuarios autenticados. Requiere lógica de autorización
PresencePresenceChannelExtensió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;
});

Autorización mediante clases de canal

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.
npm run build

Ejemplo práctico: actualización en tiempo real del estado del pedido

1

Activar broadcasting

php artisan install:broadcasting --reverb
Arranca el servidor Reverb y el worker de cola.
php artisan reverb:start
php artisan queue:work
2

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,
        ];
    }
}
3

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;
});
4

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);
5

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.
Última modificación el 13 de julio de 2026