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

# Autorisation et surcharge des canaux de broadcast dans un package

> Explique l'ordre d'évaluation de l'autorisation lorsqu'un package enregistre des canaux privés, comment l'application qui l'utilise peut les surcharger et comment le vérifier avec des tests HTTP.

Lorsqu'un package diffuse des événements en temps réel, concevez séparément la **définition du nom du canal** et la **vérification de qui peut le rejoindre**. Un canal que le package enregistre dans `boot()` peut être surchargé si le `routes/channels.php` de l'application utilise le même nom. Comprendre cet ordre d'enregistrement et d'évaluation permet de réduire les bugs lors de la maintenance.

Cette page s'appuie sur la documentation officielle de Laravel sur le [broadcasting](https://kawax.biz/fr/broadcasting.md) et sur l'implémentation de la dernière version `v13.42.0`, utilisée pour la vérification. Pour l'envoi des événements, consultez [broadcasting](https://kawax.biz/fr/broadcasting.md). Pour le chargement des providers, consultez [découverte automatique des packages](https://kawax.biz/fr/advanced/package-discovery.md).

## Fonctionnement de l'autorisation des canaux

Lorsqu'un client s'abonne à un canal privé, il envoie une requête à `/broadcasting/auth`. `BroadcastController::authenticate()` transmet le traitement à `Broadcast::auth()`, et le `Broadcaster` évalue les callbacks enregistrés dans l'ordre.

Les règles d'évaluation sont les suivantes :

* Si un callback retourne `false`, une `AccessDeniedHttpException` est levée immédiatement.
* S'il retourne une valeur vraie comme `true`, l'autorisation est accordée à ce moment-là.
* S'il retourne une valeur fausse comme `null`, l'évaluation passe au callback enregistré suivant. Si aucun n'accorde l'accès, une `AccessDeniedHttpException` est levée à la fin.

> [!NOTE]
>
> Les drivers `Pusher` et `Reverb` retirent les préfixes `private-` et `presence-` avant l'autorisation. N'incluez donc pas le préfixe dans les noms de canaux que vous enregistrez.

## Enregistrer un canal dans le package

Prenons l'exemple d'un package fictif `Acme\Orders` qui diffuse les changements d'état des commandes. Le nom du canal est `acme.orders.{order}`, et seul le propriétaire de la commande peut s'y abonner.

Dans le `ServiceProvider` du package, appelez `Broadcast::channel()` dans `boot()`. Déléguez la vérification à une classe du package.

```php theme={null}
use Acme\Orders\Broadcasting\OrderChannel;
use Illuminate\Support\Facades\Broadcast;

public function boot(): void
{
    Broadcast::channel('acme.orders.{order}', OrderChannel::class);
}
```

```php theme={null}
<?php

namespace Acme\Orders\Broadcasting;

use Acme\Orders\Models\Order;
use Illuminate\Contracts\Auth\Authenticatable;

class OrderChannel
{
    public function join(Authenticatable $user, Order $order): bool
    {
        return $user->getAuthIdentifier() === $order->owner_id;
    }
}
```

Le premier argument de `join()` reçoit l'utilisateur au moment de l'autorisation. Les arguments suivants reçoivent les valeurs des `{...}` du nom du canal. Si le nom du paramètre `{order}` correspond à `Order $order` et que le type est une sous-classe de `UrlRoutable`, le route model binding s'applique.

> [!NOTE]
>
> Le `$callback` de `Broadcast::channel()` peut être un `callable` ou le nom d'une classe possédant une méthode `join()`. Pour un nom de classe, `Broadcaster::normalizeChannelHandlerToCallable()` crée l'instance via le conteneur, puis appelle `join()`.

## Surcharge par l'application

Le fichier que l'application passe à `withBroadcasting()` (en général `routes/channels.php`) est chargé dans un callback `booted` que `withBroadcasting()` enregistre. Les callbacks `booted` s'exécutent une fois le `boot()` de tous les service providers terminé : l'enregistrement fait dans le `boot()` du package a donc lieu en premier.

| Ordre | Traitement | Ce qui est enregistré |
| - | - | - |
| 1 | `boot()` du package | Le callback de `acme.orders.{order}` |
| 2 | Chargement des routes dans le `booted` de l'application | Le callback de `routes/channels.php` |

`Broadcaster::channel()` stocke les callbacks dans un tableau interne dont la clé est le nom du canal. Si l'application enregistre le même nom, le second enregistrement remplace donc celui du package. Laravel ne signale pas un nom en double comme une erreur.

Pour éviter la surcharge, rendez le nom du canal unique. Par exemple, avec un préfixe propre au package comme dans `acme.orders.{order}`, il devient moins probable que l'application enregistre le même nom.
Le nom du canal est un contrat public avec les clients. Une fois choisi, ne le modifiez pas. Si vous le modifiez, les anciens clients ne pourront plus s'abonner.

> [!WARNING]
>
> Entre deux canaux du même nom, celui enregistré en dernier l'emporte sans avertissement. `php artisan channel:list` affiche le nom du canal et sa cible de résolution (nom de classe ou `Closure`), ce qui permet de vérifier quel enregistrement est en vigueur.

## Options du canal et guards

Le troisième argument `$options` de `Broadcast::channel()` est enregistré comme configuration propre au canal. Si vous indiquez `guards`, les guards utilisés pour l'authentification sont essayés dans l'ordre.

```php theme={null}
Broadcast::channel('acme.orders.{order}', OrderChannel::class, [
    'guards' => ['web', 'api'],
]);
```

Si `guards` est omis, l'utilisateur par défaut de la requête (`$request->user()`) est utilisé pour l'autorisation. Si `guards` est indiqué, `$request->user($guard)` est appelé dans l'ordre depuis le début, et le premier utilisateur obtenu est utilisé. Si le package ne fige pas les noms de guards et les expose comme valeur de configuration, l'application peut les choisir.

## Vérifier l'enregistrement des canaux dans les tests

Les canaux enregistrés s'obtiennent sous forme de `Collection` avec la méthode `getChannels()` du driver. Les clés sont les noms de canaux eux-mêmes.

```php theme={null}
use Illuminate\Support\Facades\Broadcast;

public function test_package_registers_order_channel(): void
{
    $channels = Broadcast::driver()->getChannels();

    $this->assertTrue($channels->has('acme.orders.{order}'));
}
```

Vérifiez le résultat de l'autorisation avec un test HTTP sur `/broadcasting/auth`. Les drivers `null` et `log` ne retournent rien depuis `auth()` et ne conviennent donc pas à ce test. Les canaux sont enregistrés sur le driver par défaut au démarrage de l'application : définissez donc `BROADCAST_CONNECTION` sur `reverb` ou `pusher`, par exemple dans le `phpunit.xml` de test, avant d'envoyer la requête authentifiée.

```php theme={null}
use Acme\Orders\Models\Order;
use App\Models\User;

public function test_owner_can_join_order_channel(): void
{
    $user = User::factory()->create();
    $order = Order::factory()->for($user, 'owner')->create();

    $this->actingAs($user)
        ->post('/broadcasting/auth', [
            'channel_name' => 'private-acme.orders.'.$order->id,
            'socket_id' => '1234.5678',
        ])
        ->assertOk();
}
```

> [!TIP]
>
> La route `/broadcasting/auth` doit être enregistrée dans l'application de test. C'est `Broadcast::routes()` qui l'enregistre, et `BroadcastManager::channelRoutes()` se contente de déléguer le même traitement à `routes()`. Si les routes sont en cache, `routes()` ne fait rien.

## Points d'attention pour la maintenance

* Le nom du canal est un contrat public. Si vous le renommez, les clients existants ne pourront plus s'abonner.
* Les canaux basés sur une classe sont résolus par le `Container`. Utilisez pour les dépendances du constructeur des types que le conteneur sait résoudre.

## Résumé

L'autorisation des canaux d'un package fonctionne dès que `Broadcast::channel()` est enregistré dans `boot()`. Si le `routes/channels.php` de l'application enregistre ensuite le même nom, l'autorisation du package est remplacée. Préfixer le nom du canal, isoler la vérification dans une classe et contrôler le résultat de `/broadcasting/auth` avec des tests HTTP rend le package plus facile à maintenir.

## Sources primaires consultées

* [Documentation officielle de Laravel : broadcasting](https://github.com/laravel/docs/blob/13.x/broadcasting.md)
* [Framework v13.42.0 : Broadcaster](https://github.com/laravel/framework/blob/v13.42.0/src/Illuminate/Broadcasting/Broadcasters/Broadcaster.php)
* [Framework v13.42.0 : UsePusherChannelConventions](https://github.com/laravel/framework/blob/v13.42.0/src/Illuminate/Broadcasting/Broadcasters/UsePusherChannelConventions.php)
* [Framework v13.42.0 : BroadcastManager](https://github.com/laravel/framework/blob/v13.42.0/src/Illuminate/Broadcasting/BroadcastManager.php)
* [Framework v13.42.0 : ApplicationBuilder](https://github.com/laravel/framework/blob/v13.42.0/src/Illuminate/Foundation/Configuration/ApplicationBuilder.php)
* [Framework v13.42.0 : BroadcastController](https://github.com/laravel/framework/blob/v13.42.0/src/Illuminate/Broadcasting/BroadcastController.php)
* [Framework v13.42.0 : commande channel:list](https://github.com/laravel/framework/blob/v13.42.0/src/Illuminate/Foundation/Console/ChannelListCommand.php)


## Related topics

- [Canaux de notification personnalisés dans un package et vérification de l'envoi](https://kawax.biz/fr/advanced/package-notification-channels.md)
- [Enregistrer et tester des transports de mail dans un package](https://kawax.biz/fr/advanced/package-mail-transports.md)
- [Surcharge et mise à jour des traductions d'un package](https://kawax.biz/fr/advanced/package-translations.md)
- [Attributs contextuels et résolution des dépendances dans un package](https://kawax.biz/fr/advanced/package-contextual-attributes.md)
- [Enregistrement et cache des routes d'un package](https://kawax.biz/fr/advanced/package-routes.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.