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
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.
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
| Canale | Classe | Descrizione |
|---|
| Public | Channel | Nessuna autenticazione. Sottoscrivibile da tutti |
| Private | PrivateChannel | Solo utenti autenticati. Serve la logica di autorizzazione |
| Presence | PresenceChannel | Estensione 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.
Esempio pratico: aggiornamento in tempo reale dello stato di un ordine
Attiva il broadcasting
php artisan install:broadcasting --reverb
Avvia server Reverb e worker.php artisan reverb:start
php artisan queue:work
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,
];
}
}
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;
});
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);
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.