Vai al contenuto principale

Cos’è il broadcasting

Con i WebSocket puoi inviare dati in tempo reale dal server al client. Il broadcasting di Laravel è il meccanismo che veicola gli eventi lato server al JavaScript frontend via WebSocket. Ad esempio, al cambio di stato di un ordine, puoi mostrare l’aggiornamento subito nel browser senza ricaricare la pagina. La forza del broadcasting di Laravel è condividere direttamente nome dell’evento e dati tra server e client.
Il broadcasting è costruito sul sistema di eventi di Laravel. Padroneggia prima le basi di Eventi e listener.

Setup

Nelle nuove app Laravel il broadcasting è disabilitato di default. Attivalo con il comando Artisan install:broadcasting.
php artisan install:broadcasting
Ti verrà chiesto quale servizio usare. Vengono creati config/broadcasting.php e routes/channels.php.

Laravel Reverb

Da Laravel 11 in poi si consiglia il server WebSocket ufficiale Laravel Reverb. Reverb è self-hosted e realizza la comunicazione real-time senza servizi esterni.

Installazione

Con l’opzione --reverb del comando install:broadcasting esegui in blocco l’installazione dei pacchetti Composer/NPM e la configurazione di .env.
php artisan install:broadcasting --reverb
Manualmente:
composer require laravel/reverb

php artisan reverb:install

Valori principali in .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}"

Avvio del server Reverb

php artisan reverb:start
In produzione gestiscilo come demone con Supervisor o simili.
Gli eventi broadcast passano per la coda. Oltre a Reverb devi avere anche i queue worker attivi.
php artisan queue:work

Creazione di eventi broadcast

Genera la classe evento

php artisan make:event OrderShipmentStatusUpdated
Fai implementare 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,
    ) {}

    /**
     * Canali su cui l'evento viene trasmesso
     */
    public function broadcastOn(): Channel
    {
        return new PrivateChannel('orders.' . $this->order->id);
    }
}
Basta implementare ShouldBroadcast e l’evento viene trasmesso automaticamente via coda.

Personalizzare il payload

Di default vengono trasmesse tutte le proprietà public. Per filtrare usa broadcastWith.
public function broadcastWith(): array
{
    return [
        'order_id' => $this->order->id,
        'status'   => $this->order->status,
    ];
}

Nome dell’evento personalizzato

Di default il nome è quello della classe. Cambialo con broadcastAs.
public function broadcastAs(): string
{
    return 'order.status.updated';
}
Nel frontend anteponi . per disabilitare il prefisso del namespace.
Echo.private(`orders.${orderId}`)
    .listen('.order.status.updated', (e) => {
        console.log(e);
    });

Tipi di canale

CanaleClasseDescrizione
PublicChannelNessuna autenticazione. Sottoscrivibile da tutti
PrivatePrivateChannelSolo utenti autenticati. Serve la logica di autorizzazione
PresencePresenceChannelEstensione di Private. Ottieni l’elenco dei partecipanti
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;

public function broadcastOn(): Channel
{
    return new Channel('posts');
}

public function broadcastOn(): Channel
{
    return new PrivateChannel('orders.' . $this->order->id);
}

public function broadcastOn(): Channel
{
    return new PresenceChannel('rooms.' . $this->room->id);
}
Per più canali restituisci un array.
public function broadcastOn(): array
{
    return [
        new PrivateChannel('orders.' . $this->order->id),
        new Channel('admin.orders'),
    ];
}

Autorizzazione dei canali

I canali Private e Presence effettuano un controllo di autorizzazione lato server prima della sottoscrizione.

routes/channels.php

Definisci le callback in routes/channels.php (creato da 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;
});
Il primo argomento è l’utente autenticato, gli altri sono le wildcard nel nome del canale. Restituisci true (o truthy) per autorizzare, false per negare.
Puoi usare il route model binding. Con nome canale orders.{order}, viene passata un’istanza Order.
Broadcast::channel('orders.{order}', function (User $user, Order $order) {
    return $user->id === $order->user_id;
});

Classi di canale per l’autorizzazione

Se i canali crescono organizza con classi.
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;
    }
}
Registra in routes/channels.php.
use App\Broadcasting\OrderChannel;

Broadcast::channel('orders.{order}', OrderChannel::class);

Emettere gli eventi

Gli eventi con ShouldBroadcast si emettono come i normali eventi.
use App\Events\OrderShipmentStatusUpdated;

OrderShipmentStatusUpdated::dispatch($order);
Per non inviarli anche a se stessi usa toOthers.
broadcast(new OrderShipmentStatusUpdated($order))->toOthers();
toOthers richiede che la classe evento usi il trait InteractsWithSockets.

Ricezione nel frontend

Setup di Laravel Echo

Con Reverb, configura Echo in 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'],
});

Ascolto degli eventi

// Public
Echo.channel('posts')
    .listen('PostPublished', (e) => {
        console.log(e.post);
    });

// Private
Echo.private(`orders.${orderId}`)
    .listen('OrderShipmentStatusUpdated', (e) => {
        console.log(e.order);
    });

// Presence
Echo.join(`rooms.${roomId}`)
    .here((users) => {
        console.log('Membri attuali:', users);
    })
    .joining((user) => {
        console.log(user.name, 'è entrato');
    })
    .leaving((user) => {
        console.log(user.name, 'è uscito');
    })
    .listen('MessagePosted', (e) => {
        console.log(e.message);
    });

Hook React / Vue

Con gli starter kit React/Vue puoi usare hook dedicati.
import { useEcho } from "@laravel/echo-react";

useEcho(
    `orders.${orderId}`,
    "OrderShipmentStatusUpdated",
    (e) => {
        console.log(e.order);
    },
);

import { useEchoPublic } from "@laravel/echo-react";

useEchoPublic("posts", "PostPublished", (e) => {
    console.log(e.post);
});
useEcho abbandona automaticamente il canale allo unmount del componente.
Prima del build assicurati che .env contenga le VITE_REVERB_* corrette.
npm run build

Esempio pratico: aggiornamento in tempo reale dello stato di un ordine

1

Attiva il broadcasting

php artisan install:broadcasting --reverb
Avvia server Reverb e worker.
php artisan reverb:start
php artisan queue:work
2

Crea l'evento

php artisan make:event OrderShipmentStatusUpdated
<?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

Definisci l'autorizzazione del canale

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

Emetti l'evento

Dopo l’aggiornamento dello stato dell’ordine, in un controller o job:
use App\Events\OrderShipmentStatusUpdated;

$order->update(['status' => 'shipped']);

OrderShipmentStatusUpdated::dispatch($order);
5

Ricevi nel frontend

Da template Blade o componente React/Vue:
Echo.private(`orders.${orderId}`)
    .listen('OrderShipmentStatusUpdated', (e) => {
        document.getElementById('status').textContent = e.status;
    });

Prossimi passi

Laravel Reverb

Setup, esercizio in produzione e scaling del server Reverb.

Code e job

Il broadcasting passa per la coda: configura e gestisci le code.

Eventi e listener

Il sistema di eventi di Laravel alla base del broadcasting.
Ultima modifica il 13 luglio 2026