Passer au contenu principal

Qu’est-ce que le broadcasting

Les WebSockets permettent au serveur d’envoyer des données au client en temps réel. Le broadcasting Laravel achemine les événements côté serveur vers le JavaScript frontend via WebSocket. Par exemple, quand le statut d’une commande change, l’affichage se met à jour dans le navigateur sans recharger la page. La force du broadcasting Laravel est de partager tel quel nom d’événement et données entre serveur et client.
Le broadcasting repose sur le système d’événements Laravel. Familiarisez-vous d’abord avec Événements et listeners.

Mise en place

Le broadcasting est désactivé par défaut dans un nouveau projet. Activez-le via install:broadcasting.
php artisan install:broadcasting
La commande vous demande quel service utiliser et génère config/broadcasting.php et routes/channels.php.

Laravel Reverb

Depuis Laravel 11, le serveur WebSocket officiel Laravel Reverb est recommandé. Self-hosted, il fournit du temps réel sans service externe.

Installation

install:broadcasting --reverb installe les packages Composer/NPM et met à jour .env en une commande.
php artisan install:broadcasting --reverb
Installation manuelle :
composer require laravel/reverb

php artisan reverb:install

Variables .env principales

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}"

Démarrer Reverb

php artisan reverb:start
En production, Supervisor (ou équivalent) fait tourner Reverb en daemon.
Les événements de broadcast passent par la queue. Démarrez aussi un worker :
php artisan queue:work

Créer un événement de broadcast

Générer l’événement

php artisan make:event OrderShipmentStatusUpdated
Implémentez l’interface 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,
    ) {}

    /**
     * Canaux sur lesquels l'événement est diffusé.
     */
    public function broadcastOn(): Channel
    {
        return new PrivateChannel('orders.' . $this->order->id);
    }
}
Avec ShouldBroadcast, l’événement dispatché est automatiquement mis en file puis diffusé.

Personnaliser la charge utile

Par défaut, toutes les propriétés public sont incluses. Filtrez avec broadcastWith.
public function broadcastWith(): array
{
    return [
        'order_id' => $this->order->id,
        'status'   => $this->order->status,
    ];
}

Personnaliser le nom d’événement

Le nom de classe sert par défaut. Personnalisez avec broadcastAs.
public function broadcastAs(): string
{
    return 'order.status.updated';
}
Côté frontend, préfixez de . pour désactiver le namespace applicatif.
Echo.private(`orders.${orderId}`)
    .listen('.order.status.updated', (e) => {
        console.log(e);
    });

Types de canaux

CanalClasseDescription
PublicChannelAucune auth, souscription libre
PrivatePrivateChannelAuthentifiés uniquement, autorisation requise
PresencePresenceChannelExtension de Private, liste les membres
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;

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

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

// Presence
public function broadcastOn(): Channel
{
    return new PresenceChannel('rooms.' . $this->room->id);
}
Plusieurs canaux : retournez un tableau.
public function broadcastOn(): array
{
    return [
        new PrivateChannel('orders.' . $this->order->id),
        new Channel('admin.orders'),
    ];
}

Autorisation de canal

Private et Presence exigent une vérification serveur avant souscription.

routes/channels.php

Généré par 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;
});
Premier argument : utilisateur authentifié ; suivants : wildcards du nom de canal. Retour truthy = autorisé ; false = refusé.
Route model binding disponible. orders.{order} reçoit une instance de Order.
Broadcast::channel('orders.{order}', function (User $user, Order $order) {
    return $user->id === $order->user_id;
});

Classe de canal

Pour ranger le code quand il y en a beaucoup :
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;
    }
}
Enregistrez dans routes/channels.php.
use App\Broadcasting\OrderChannel;

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

Déclencher l’événement

Comme un événement normal.
use App\Events\OrderShipmentStatusUpdated;

OrderShipmentStatusUpdated::dispatch($order);
Pour exclure l’expéditeur, utilisez toOthers.
broadcast(new OrderShipmentStatusUpdated($order))->toOthers();
toOthers requiert le trait InteractsWithSockets.

Réception côté frontend

Laravel Echo

Installez et configurez dans 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'],
});

Écouter les événements

// 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('Membres actuels :', users);
    })
    .joining((user) => {
        console.log(user.name, 'a rejoint');
    })
    .leaving((user) => {
        console.log(user.name, 'a quitté');
    })
    .listen('MessagePosted', (e) => {
        console.log(e.message);
    });

Hooks React / Vue

Les kits de démarrage React/Vue proposent des hooks dédiés.
import { useEcho } from "@laravel/echo-react";

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

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

useEchoPublic("posts", "PostPublished", (e) => {
    console.log(e.post);
});
Ils quittent automatiquement le canal au démontage.
Vérifiez que VITE_REVERB_* sont bien renseignés dans .env avant le build.
npm run build

Exemple : mise à jour temps réel d’un statut de commande

1

Activer le broadcasting

php artisan install:broadcasting --reverb
Démarrez Reverb et un worker de queue.
php artisan reverb:start
php artisan queue:work
2

Créer l'événement

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

Autorisation de canal

Dans 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

Dispatcher l'événement

Depuis un contrôleur ou un job après mise à jour.
use App\Events\OrderShipmentStatusUpdated;

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

OrderShipmentStatusUpdated::dispatch($order);
5

Écouter côté frontend

Script inline dans Blade ou composant React/Vue.
Echo.private(`orders.${orderId}`)
    .listen('OrderShipmentStatusUpdated', (e) => {
        document.getElementById('status').textContent = e.status;
    });

Prochaines étapes

Laravel Reverb

Setup, exploitation et scaling du serveur Reverb.

Queues et jobs

Le broadcasting passe par la queue : configurez-la correctement.

Événements et listeners

Les fondations du système d’événements Laravel.
Dernière modification le 13 juillet 2026