> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Broadcasting

> Implémentez la communication WebSocket temps réel avec le broadcasting Laravel et Laravel Reverb.

## 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.

<Info>
  Le broadcasting repose sur le système d'événements Laravel.
  Familiarisez-vous d'abord avec [Événements et listeners](/fr/events).
</Info>

```mermaid theme={null}
flowchart LR
    A["Événement côté serveur<br>dispatch()"] --> B["Driver de broadcast<br>(Reverb, etc.)"]
    B --> C["Serveur<br>WebSocket"]
    C --> D["Vérification<br>d'autorisation"]
    D --> E["Client<br>Laravel Echo"]
    E --> F["Mise à jour temps<br>réel de l'UI"]
```

## Mise en place

Le broadcasting est désactivé par défaut dans un nouveau projet.
Activez-le via `install:broadcasting`.

```shell theme={null}
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.

```shell theme={null}
php artisan install:broadcasting --reverb
```

Installation manuelle :

```shell theme={null}
composer require laravel/reverb

php artisan reverb:install
```

### Variables `.env` principales

```ini theme={null}
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

```shell theme={null}
php artisan reverb:start
```

En production, Supervisor (ou équivalent) fait tourner Reverb en daemon.

<Tip>
  Les événements de broadcast passent par la queue. Démarrez aussi un worker :

  ```shell theme={null}
  php artisan queue:work
  ```
</Tip>

## Créer un événement de broadcast

### Générer l'événement

```shell theme={null}
php artisan make:event OrderShipmentStatusUpdated
```

Implémentez l'interface `ShouldBroadcast`.

```php theme={null}
<?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`.

```php theme={null}
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`.

```php theme={null}
public function broadcastAs(): string
{
    return 'order.status.updated';
}
```

Côté frontend, préfixez de `.` pour désactiver le namespace applicatif.

```js theme={null}
Echo.private(`orders.${orderId}`)
    .listen('.order.status.updated', (e) => {
        console.log(e);
    });
```

## Types de canaux

| Canal        | Classe            | Description                                   |
| ------------ | ----------------- | --------------------------------------------- |
| **Public**   | `Channel`         | Aucune auth, souscription libre               |
| **Private**  | `PrivateChannel`  | Authentifiés uniquement, autorisation requise |
| **Presence** | `PresenceChannel` | Extension de Private, liste les membres       |

```php theme={null}
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.

```php theme={null}
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`.

```php theme={null}
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é.

<Info>
  Route model binding disponible.
  `orders.{order}` reçoit une instance de `Order`.
</Info>

```php theme={null}
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 :

```shell theme={null}
php artisan make:channel OrderChannel
```

```php theme={null}
<?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`.

```php theme={null}
use App\Broadcasting\OrderChannel;

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

## Déclencher l'événement

Comme un événement normal.

```php theme={null}
use App\Events\OrderShipmentStatusUpdated;

OrderShipmentStatusUpdated::dispatch($order);
```

Pour exclure l'expéditeur, utilisez `toOthers`.

```php theme={null}
broadcast(new OrderShipmentStatusUpdated($order))->toOthers();
```

<Warning>
  `toOthers` requiert le trait `InteractsWithSockets`.
</Warning>

## Réception côté frontend

### Laravel Echo

Installez et configurez dans `resources/js/bootstrap.js`.

```shell theme={null}
npm install --save-dev laravel-echo pusher-js
```

```js theme={null}
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

```js theme={null}
// 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.

```js theme={null}
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.

<Tip>
  Vérifiez que `VITE_REVERB_*` sont bien renseignés dans `.env` avant le build.

  ```shell theme={null}
  npm run build
  ```
</Tip>

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

<Steps>
  <Step title="Activer le broadcasting">
    ```shell theme={null}
    php artisan install:broadcasting --reverb
    ```

    Démarrez Reverb et un worker de queue.

    ```shell theme={null}
    php artisan reverb:start
    php artisan queue:work
    ```
  </Step>

  <Step title="Créer l'événement">
    ```shell theme={null}
    php artisan make:event OrderShipmentStatusUpdated
    ```

    Éditez `app/Events/OrderShipmentStatusUpdated.php`.

    ```php theme={null}
    <?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,
            ];
        }
    }
    ```
  </Step>

  <Step title="Autorisation de canal">
    Dans `routes/channels.php`.

    ```php theme={null}
    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;
    });
    ```
  </Step>

  <Step title="Dispatcher l'événement">
    Depuis un contrôleur ou un job après mise à jour.

    ```php theme={null}
    use App\Events\OrderShipmentStatusUpdated;

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

    OrderShipmentStatusUpdated::dispatch($order);
    ```
  </Step>

  <Step title="Écouter côté frontend">
    Script inline dans Blade ou composant React/Vue.

    ```js theme={null}
    Echo.private(`orders.${orderId}`)
        .listen('OrderShipmentStatusUpdated', (e) => {
            document.getElementById('status').textContent = e.status;
        });
    ```
  </Step>
</Steps>

## Prochaines étapes

<Card title="Laravel Reverb" href="/fr/reverb">
  Setup, exploitation et scaling du serveur Reverb.
</Card>

<Card title="Queues et jobs" href="/fr/queues">
  Le broadcasting passe par la queue : configurez-la correctement.
</Card>

<Card title="Événements et listeners" href="/fr/events">
  Les fondations du système d'événements Laravel.
</Card>


## Related topics

- [FAQ sur la nouvelle structure d'application Laravel 11+](/fr/advanced/app-structure-faq.md)
- [Streaming](/fr/packages/laravel-copilot-sdk/streaming.md)
- [Laravel Reverb](/fr/reverb.md)
- [Structure d'application Laravel 11+](/fr/advanced/app-structure.md)
- [Laravel AI SDK](/fr/ai-sdk.md)
