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

> Erläutert, wie Sie mit Laravels Broadcasting und Laravel Reverb Echtzeitkommunikation über WebSockets umsetzen.

## Was ist Broadcasting?

Mit WebSockets können Daten in Echtzeit vom Server zum Client gesendet werden.
Das Broadcasting von Laravel ist ein Mechanismus, der serverseitige Events per WebSocket an das JavaScript im Frontend ausliefert.

Wenn sich zum Beispiel der Status einer Bestellung ändert, kann die Änderung im Browser sofort dargestellt werden, ohne dass die Seite neu geladen werden muss.
Die Stärke von Laravels Broadcasting liegt darin, dass Sie den Event-Namen und die Daten der Serverseite unverändert mit der Clientseite teilen können.

<Info>
  Broadcasting baut auf dem Event-System von Laravel auf.
  Wir empfehlen, zunächst die Grundlagen zu [Events und Listenern](/de/events) zu verstehen.
</Info>

```mermaid theme={null}
flowchart LR
    A["Serverseite<br>Event auslösen<br>dispatch()"] --> B["Broadcast-<br>Treiber<br>(Reverb usw.)"]
    B --> C["WebSocket-<br>Server"]
    C --> D["Channel-<br>Autorisierung"]
    D --> E["Client<br>Laravel Echo"]
    E --> F["Echtzeit-<br>Aktualisierung der UI"]
```

## Einrichtung

In neuen Laravel-Anwendungen ist Broadcasting standardmäßig deaktiviert.
Aktivieren Sie es mit dem Artisan-Befehl `install:broadcasting`.

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

Dieser Befehl fragt Sie nach dem gewünschten Broadcast-Dienst.
Zudem werden `config/broadcasting.php` und `routes/channels.php` erzeugt.

## Laravel Reverb

Ab Laravel 11 wird der offizielle WebSocket-Server **Laravel Reverb** empfohlen.
Reverb ist selbst gehostet und ermöglicht Echtzeitkommunikation, ohne dass zusätzliche externe Dienste erforderlich sind.

### Installation

Wird der Befehl `install:broadcasting` mit der Option `--reverb` aufgerufen, werden die notwendigen Composer- und NPM-Pakete für Reverb installiert und die `.env` in einem Schritt konfiguriert.

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

Für eine manuelle Installation fügen Sie das Paket zunächst über Composer hinzu und führen dann den Installationsbefehl aus.

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

php artisan reverb:install
```

### Wichtige Einstellungen in der .env

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

### Reverb-Server starten

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

In der Produktion verwalten Sie den Server als Daemon über einen Prozessmanager wie Supervisor.

<Tip>
  Broadcast-Events werden über die Queue verarbeitet.
  Sie müssen daher zusätzlich zum Reverb-Server auch einen Queue-Worker starten.

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

## Broadcast-Event erstellen

### Event-Klasse erzeugen

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

Lassen Sie die erzeugte Event-Klasse das Interface `ShouldBroadcast` implementieren.

```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,
    ) {}

    /**
     * Liefert die Channels zurück, über die das Event broadcastet werden soll.
     */
    public function broadcastOn(): Channel
    {
        return new PrivateChannel('orders.' . $this->order->id);
    }
}
```

Durch die Implementierung von `ShouldBroadcast` wird das Event beim Auslösen automatisch über die Queue broadcastet.

### Broadcast-Daten anpassen

Standardmäßig werden alle `public`-Eigenschaften der Event-Klasse in den Broadcast-Payload aufgenommen.
Definieren Sie die Methode `broadcastWith`, um die gesendeten Daten einzuschränken.

```php theme={null}
public function broadcastWith(): array
{
    return [
        'order_id' => $this->order->id,
        'status'   => $this->order->status,
    ];
}
```

### Broadcast-Namen anpassen

Standardmäßig ist der Klassenname zugleich der Event-Name.
Mit `broadcastAs` können Sie einen eigenen Namen festlegen.

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

Wenn Sie im Frontend darauf hören, setzen Sie einen führenden `.`, um das Namespace-Präfix der Anwendung zu unterdrücken.

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

## Channel-Typen

| Channel      | Klasse            | Beschreibung                                                      |
| ------------ | ----------------- | ----------------------------------------------------------------- |
| **Public**   | `Channel`         | Keine Authentifizierung erforderlich; jeder kann abonnieren       |
| **Private**  | `PrivateChannel`  | Nur authentifizierte Benutzer; Autorisierungslogik notwendig      |
| **Presence** | `PresenceChannel` | Erweiterung von Private; Liste der Teilnehmer im Channel abrufbar |

```php theme={null}
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;

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

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

// Presence-Channel
public function broadcastOn(): Channel
{
    return new PresenceChannel('rooms.' . $this->room->id);
}
```

Um auf mehreren Channels zu broadcasten, geben Sie ein Array zurück.

```php theme={null}
public function broadcastOn(): array
{
    return [
        new PrivateChannel('orders.' . $this->order->id),
        new Channel('admin.orders'),
    ];
}
```

## Channel-Autorisierung

Für Private- und Presence-Channels findet vor dem Abonnieren eine serverseitige Autorisierungsprüfung statt.

### routes/channels.php

Definieren Sie den Autorisierungs-Callback in der Datei `routes/channels.php`, die vom Befehl `install:broadcasting` erzeugt wird.

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

Der erste Parameter des Callbacks ist der authentifizierte Benutzer, die weiteren Parameter entsprechen den Platzhaltern im Channel-Namen.
Bei einer Rückgabe von `true` oder einem truthy-Wert ist die Autorisierung erfolgreich, `false` führt zur Ablehnung.

<Info>
  Auch Route Model Binding lässt sich verwenden.
  Verwenden Sie den Channel-Namen `orders.{order}`, erhalten Sie eine `Order`-Modellinstanz.
</Info>

```php theme={null}
Broadcast::channel('orders.{order}', function (User $user, Order $order) {
    return $user->id === $order->user_id;
});
```

### Autorisierung über eine Channel-Klasse

Wenn die Anzahl der Channels wächst, können Sie diese über Channel-Klassen strukturieren.

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

Registrieren Sie die Klasse in `routes/channels.php`.

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

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

## Events auslösen

Events, die `ShouldBroadcast` implementieren, werden wie gewöhnliche Events ausgelöst.

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

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

Um das Event allen anderen Benutzern außer dem auslösenden zu senden, verwenden Sie `toOthers`.

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

<Warning>
  Für `toOthers` muss die Event-Klasse das Trait `InteractsWithSockets` verwenden.
</Warning>

## Empfang im Frontend

### Laravel Echo einrichten

Wenn Sie Reverb verwenden, konfigurieren Sie in `resources/js/bootstrap.js` die Echo-Instanz.

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

### Auf Events hören

```js theme={null}
// Public-Channel
Echo.channel('posts')
    .listen('PostPublished', (e) => {
        console.log(e.post);
    });

// Private-Channel
Echo.private(`orders.${orderId}`)
    .listen('OrderShipmentStatusUpdated', (e) => {
        console.log(e.order);
    });

// Presence-Channel
Echo.join(`rooms.${roomId}`)
    .here((users) => {
        console.log('Aktuelle Mitglieder:', users);
    })
    .joining((user) => {
        console.log(user.name, 'ist beigetreten');
    })
    .leaving((user) => {
        console.log(user.name, 'hat den Channel verlassen');
    })
    .listen('MessagePosted', (e) => {
        console.log(e.message);
    });
```

### React- und Vue-Hooks nutzen

Bei den React- und Vue-Starter-Kits stehen spezielle Hooks zur Verfügung, mit denen der Code kompakter ausfällt.

```js theme={null}
import { useEcho } from "@laravel/echo-react";

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

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

useEchoPublic("posts", "PostPublished", (e) => {
    console.log(e.post);
});
```

Der Hook `useEcho` verlässt den Channel beim Unmounten der Komponente automatisch.

<Tip>
  Stellen Sie vor dem Build der Frontend-Assets sicher, dass die Variablen `VITE_REVERB_*` in Ihrer `.env` korrekt gesetzt sind.

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

## Praxisbeispiel: Bestellstatus in Echtzeit aktualisieren

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

    Starten Sie den Reverb-Server und einen Queue-Worker.

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

  <Step title="Event-Klasse erstellen">
    ```shell theme={null}
    php artisan make:event OrderShipmentStatusUpdated
    ```

    Bearbeiten Sie `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="Channel-Autorisierung definieren">
    Ergänzen Sie in `routes/channels.php` die Autorisierungslogik.

    ```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="Event auslösen">
    Lösen Sie das Event in einem Controller oder Job aus, der den Bestellstatus aktualisiert.

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

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

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

  <Step title="Im Frontend darauf hören">
    Empfangen Sie das Event über ein Inline-Script in einem Blade-Template oder in einer React-/Vue-Komponente.

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

## Nächste Schritte

<Card title="Laravel Reverb" href="/de/reverb">
  Erfahren Sie mehr über die Einrichtung des Reverb-Servers, den Betrieb in der Produktion und Skalierung.
</Card>

<Card title="Queues und Jobs" href="/de/queues">
  Broadcasting wird über die Queue verarbeitet. Erfahren Sie, wie Sie Queues konfigurieren und betreiben.
</Card>

<Card title="Events und Listener" href="/de/events">
  Vertiefen Sie sich in das Event-System von Laravel, das die Grundlage für Broadcasting bildet.
</Card>


## Related topics

- [Laravel AI SDK](/de/ai-sdk.md)
- [FAQ zur neuen App-Struktur ab Laravel 11](/de/advanced/app-structure-faq.md)
- [Laravel Reverb](/de/reverb.md)
- [Anwendungsstruktur ab Laravel 11](/de/advanced/app-structure.md)
- [Streaming](/de/packages/laravel-copilot-sdk/streaming.md)
