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

# Broadcast-Kanal-Autorisierung in Paketen und Überschreiben

> Erklärt die Auswertungsreihenfolge der Autorisierung, wenn ein Paket private Kanäle registriert, wie die nutzende Anwendung sie überschreiben kann und wie Sie das mit HTTP-Tests prüfen.

Wenn ein Paket Echtzeit-Events sendet, trennen Sie beim Entwurf die **Definition des Kanalnamens** von der **Prüfung, wer beitreten darf**. Ein Kanal, den das Paket in `boot()` registriert, kann überschrieben werden, wenn die `routes/channels.php` der nutzenden Anwendung denselben Namen verwendet. Wer diese Registrierungs- und Auswertungsreihenfolge versteht, vermeidet Fehler bei der Wartung.

Diese Seite stützt sich auf die offizielle Laravel-Dokumentation zu [Broadcasting](https://kawax.biz/de/broadcasting.md) und auf die Implementierung des neuesten Releases `v13.42.0`, das zur Überprüfung verwendet wurde. Wie Sie Events senden, erfahren Sie unter [Broadcasting](https://kawax.biz/de/broadcasting.md). Wie Provider geladen werden, erfahren Sie unter [Paket-Auto-Discovery](https://kawax.biz/de/advanced/package-discovery.md).

## So funktioniert die Kanal-Autorisierung

Wenn ein Client einen privaten Kanal abonniert, sendet er einen Request an `/broadcasting/auth`. `BroadcastController::authenticate()` übergibt die Verarbeitung an `Broadcast::auth()`, und der `Broadcaster` wertet die registrierten Callbacks der Reihe nach aus.

Für die Auswertung gelten folgende Regeln:

* Gibt ein Callback `false` zurück, wird sofort eine `AccessDeniedHttpException` geworfen.
* Gibt ein Callback einen wahren Wert wie `true` zurück, ist die Autorisierung an dieser Stelle erfolgreich.
* Gibt ein Callback einen falschen Wert wie `null` zurück, geht es mit dem nächsten registrierten Callback weiter. Gewährt keiner den Zugriff, wird am Ende eine `AccessDeniedHttpException` geworfen.

> [!NOTE]
>
> Die Treiber `Pusher` und `Reverb` entfernen vor der Autorisierung die Präfixe `private-` und `presence-`. Nehmen Sie das Präfix deshalb nicht in die registrierten Kanalnamen auf.

## Einen Kanal im Paket registrieren

Als Beispiel sendet ein fiktives Paket `Acme\Orders` Statusänderungen von Bestellungen. Der Kanalname lautet `acme.orders.{order}`, und nur der Eigentümer der Bestellung darf ihn abonnieren.

Rufen Sie im `ServiceProvider` des Pakets `Broadcast::channel()` innerhalb von `boot()` auf. Die Prüfung delegieren Sie an eine Klasse im Paket.

```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;
    }
}
```

Das erste Argument von `join()` erhält den Benutzer zum Zeitpunkt der Autorisierung. Die weiteren Argumente erhalten die Werte der `{...}`-Platzhalter im Kanalnamen. Stimmt der Parametername `{order}` mit `Order $order` überein und ist der Typ eine Unterklasse von `UrlRoutable`, greift das Route Model Binding.

> [!NOTE]
>
> Als `$callback` von `Broadcast::channel()` können Sie ein `callable` oder den Namen einer Klasse mit einer `join()`-Methode angeben. Bei einem Klassennamen erzeugt `Broadcaster::normalizeChannelHandlerToCallable()` die Instanz über den Container und ruft anschließend `join()` auf.

## Überschreiben durch die nutzende Anwendung

Die Datei, die die nutzende Anwendung an `withBroadcasting()` übergibt (normalerweise `routes/channels.php`), wird in einem `booted`-Callback geladen, den `withBroadcasting()` registriert. `booted`-Callbacks laufen erst, nachdem `boot()` aller Service Provider abgeschlossen ist. Die Registrierung in `boot()` des Pakets erfolgt daher zuerst.

| Reihenfolge | Verarbeitung | Was registriert wird |
| - | - | - |
| 1 | `boot()` des Pakets | Der Callback für `acme.orders.{order}` |
| 2 | Laden der Routen im `booted`-Callback der Anwendung | Der Callback aus `routes/channels.php` |

`Broadcaster::channel()` speichert die Callbacks in einem internen Array mit dem Kanalnamen als Schlüssel. Registriert die nutzende Anwendung denselben Namen, ersetzt die zweite Registrierung die des Pakets. Laravel meldet einen doppelten Namen nicht als Fehler.

Um ein Überschreiben zu verhindern, machen Sie den Kanalnamen eindeutig. Mit einem paketspezifischen Präfix wie in `acme.orders.{order}` sinkt die Wahrscheinlichkeit, dass die nutzende Anwendung denselben Namen registriert.
Der Kanalname ist ein öffentlicher Vertrag mit den Clients. Ändern Sie ihn nicht mehr, nachdem Sie ihn festgelegt haben. Eine Änderung führt dazu, dass ältere Clients den Kanal nicht mehr abonnieren können.

> [!WARNING]
>
> Bei gleichnamigen Kanälen hat stillschweigend die später registrierte Variante Vorrang. `php artisan channel:list` zeigt den Kanalnamen und das Ziel der Auflösung (Klassenname oder `Closure`) an, sodass Sie prüfen können, welche Registrierung gilt.

## Kanaloptionen und Guards

Das dritte Argument `$options` von `Broadcast::channel()` wird als kanalspezifische Konfiguration gespeichert. Wenn Sie `guards` angeben, werden die Guards für die Authentifizierung der Reihe nach ausprobiert.

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

Ohne `guards` wird der Standardbenutzer des Requests (`$request->user()`) für die Autorisierung verwendet. Mit `guards` wird `$request->user($guard)` der Reihe nach von vorne aufgerufen, und der erste gefundene Benutzer wird verwendet. Wenn das Paket die Guard-Namen nicht fest vorgibt, sondern als Konfigurationswert bereitstellt, kann die nutzende Anwendung sie wählen.

## Die Kanalregistrierung in Tests prüfen

Registrierte Kanäle erhalten Sie über `getChannels()` des Treibers als `Collection`. Die Schlüssel sind die Kanalnamen selbst.

```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}'));
}
```

Das Ergebnis der Autorisierung prüfen Sie mit einem HTTP-Test gegen `/broadcasting/auth`. Die Treiber `null` und `log` geben aus `auth()` nichts zurück und eignen sich daher nicht für diesen Test. Kanäle werden beim Start der Anwendung beim Standardtreiber registriert. Setzen Sie deshalb `BROADCAST_CONNECTION` zum Beispiel in der `phpunit.xml` für Tests auf `reverb` oder `pusher`, bevor Sie den authentifizierten Request senden.

```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]
>
> In der Test-App muss `/broadcasting/auth` registriert sein. Diese Route registriert `Broadcast::routes()`, und `BroadcastManager::channelRoutes()` übergibt dieselbe Verarbeitung lediglich an `routes()`. Sind die Routen gecacht, tut `routes()` nichts.

## Hinweise zur Wartung

* Kanalnamen sind ein öffentlicher Vertrag. Wenn Sie einen Namen ändern, können bestehende Clients den Kanal nicht mehr abonnieren.
* Klassenbasierte Kanäle werden über den `Container` aufgelöst. Verwenden Sie für Konstruktorabhängigkeiten Typen, die der Container auflösen kann.

## Zusammenfassung

Die Kanal-Autorisierung eines Pakets funktioniert, sobald Sie `Broadcast::channel()` in `boot()` registrieren. Registriert die `routes/channels.php` der nutzenden Anwendung später denselben Namen, wird die Autorisierung des Pakets ersetzt. Ein Präfix im Kanalnamen, eine eigene Klasse für die Prüfung und HTTP-Tests für das Ergebnis von `/broadcasting/auth` machen das Paket leichter wartbar.

## Verwendete Primärquellen

* [Offizielle Laravel-Dokumentation: 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: Befehl channel:list](https://github.com/laravel/framework/blob/v13.42.0/src/Illuminate/Foundation/Console/ChannelListCommand.php)


## Related topics

- [Registrieren und Überschreiben von Policies in Paketen](https://kawax.biz/de/advanced/package-authorization.md)
- [Autorisierung (Gates und Policies)](https://kawax.biz/de/authorization.md)
- [Interna des Mercure-Broadcast-Treibers](https://kawax.biz/de/advanced/mercure-broadcasting.md)
- [Paketübersetzungen überschreiben und aktualisieren](https://kawax.biz/de/advanced/package-translations.md)
- [Paket-Views überschreiben und aktualisieren](https://kawax.biz/de/advanced/package-views.md)


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