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

> Come implementare la comunicazione in tempo reale via WebSocket usando il broadcasting di Laravel e Laravel Reverb.

## Cos'è il broadcasting

Con i WebSocket puoi inviare dati in tempo reale dal server al client.
Il broadcasting di Laravel è il meccanismo che veicola gli eventi lato server al JavaScript frontend via WebSocket.

Ad esempio, al cambio di stato di un ordine, puoi mostrare l'aggiornamento subito nel browser senza ricaricare la pagina.
La forza del broadcasting di Laravel è condividere direttamente nome dell'evento e dati tra server e client.

<Info>
  Il broadcasting è costruito sul sistema di eventi di Laravel.
  Padroneggia prima le basi di [Eventi e listener](/it/events).
</Info>

```mermaid theme={null}
flowchart LR
    A["Server<br>Emissione evento<br>dispatch()"] --> B["Driver di broadcasting<br>(es. Reverb)"]
    B --> C["Server<br>WebSocket"]
    C --> D["Autorizzazione<br>del canale"]
    D --> E["Client<br>Laravel Echo"]
    E --> F["Aggiornamento<br>UI in tempo reale"]
```

## Setup

Nelle nuove app Laravel il broadcasting è disabilitato di default.
Attivalo con il comando Artisan `install:broadcasting`.

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

Ti verrà chiesto quale servizio usare. Vengono creati `config/broadcasting.php` e `routes/channels.php`.

## Laravel Reverb

Da Laravel 11 in poi si consiglia il server WebSocket ufficiale **Laravel Reverb**.
Reverb è self-hosted e realizza la comunicazione real-time senza servizi esterni.

### Installazione

Con l'opzione `--reverb` del comando `install:broadcasting` esegui in blocco l'installazione dei pacchetti Composer/NPM e la configurazione di `.env`.

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

Manualmente:

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

php artisan reverb:install
```

### Valori principali in .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}"
```

### Avvio del server Reverb

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

In produzione gestiscilo come demone con Supervisor o simili.

<Tip>
  Gli eventi broadcast passano per la coda.
  Oltre a Reverb devi avere anche i queue worker attivi.

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

## Creazione di eventi broadcast

### Genera la classe evento

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

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

    /**
     * Canali su cui l'evento viene trasmesso
     */
    public function broadcastOn(): Channel
    {
        return new PrivateChannel('orders.' . $this->order->id);
    }
}
```

Basta implementare `ShouldBroadcast` e l'evento viene trasmesso automaticamente via coda.

### Personalizzare il payload

Di default vengono trasmesse tutte le proprietà `public`. Per filtrare usa `broadcastWith`.

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

### Nome dell'evento personalizzato

Di default il nome è quello della classe. Cambialo con `broadcastAs`.

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

Nel frontend anteponi `.` per disabilitare il prefisso del namespace.

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

## Tipi di canale

| Canale       | Classe            | Descrizione                                                |
| ------------ | ----------------- | ---------------------------------------------------------- |
| **Public**   | `Channel`         | Nessuna autenticazione. Sottoscrivibile da tutti           |
| **Private**  | `PrivateChannel`  | Solo utenti autenticati. Serve la logica di autorizzazione |
| **Presence** | `PresenceChannel` | Estensione di Private. Ottieni l'elenco dei partecipanti   |

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

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

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

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

Per più canali restituisci un array.

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

## Autorizzazione dei canali

I canali Private e Presence effettuano un controllo di autorizzazione lato server prima della sottoscrizione.

### routes/channels.php

Definisci le callback in `routes/channels.php` (creato da `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;
});
```

Il primo argomento è l'utente autenticato, gli altri sono le wildcard nel nome del canale.
Restituisci `true` (o truthy) per autorizzare, `false` per negare.

<Info>
  Puoi usare il route model binding.
  Con nome canale `orders.{order}`, viene passata un'istanza `Order`.
</Info>

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

### Classi di canale per l'autorizzazione

Se i canali crescono organizza con classi.

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

Registra in `routes/channels.php`.

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

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

## Emettere gli eventi

Gli eventi con `ShouldBroadcast` si emettono come i normali eventi.

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

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

Per non inviarli anche a se stessi usa `toOthers`.

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

<Warning>
  `toOthers` richiede che la classe evento usi il trait `InteractsWithSockets`.
</Warning>

## Ricezione nel frontend

### Setup di Laravel Echo

Con Reverb, configura Echo in `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'],
});
```

### Ascolto degli eventi

```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('Membri attuali:', users);
    })
    .joining((user) => {
        console.log(user.name, 'è entrato');
    })
    .leaving((user) => {
        console.log(user.name, 'è uscito');
    })
    .listen('MessagePosted', (e) => {
        console.log(e.message);
    });
```

### Hook React / Vue

Con gli starter kit React/Vue puoi usare hook dedicati.

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

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

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

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

`useEcho` abbandona automaticamente il canale allo unmount del componente.

<Tip>
  Prima del build assicurati che `.env` contenga le `VITE_REVERB_*` corrette.

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

## Esempio pratico: aggiornamento in tempo reale dello stato di un ordine

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

    Avvia server Reverb e worker.

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

  <Step title="Crea l'evento">
    ```shell theme={null}
    php artisan make:event OrderShipmentStatusUpdated
    ```

    ```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="Definisci l'autorizzazione del canale">
    ```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="Emetti l'evento">
    Dopo l'aggiornamento dello stato dell'ordine, in un controller o job:

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

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

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

  <Step title="Ricevi nel frontend">
    Da template Blade o componente React/Vue:

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

## Prossimi passi

<Card title="Laravel Reverb" href="/it/reverb">
  Setup, esercizio in produzione e scaling del server Reverb.
</Card>

<Card title="Code e job" href="/it/queues">
  Il broadcasting passa per la coda: configura e gestisci le code.
</Card>

<Card title="Eventi e listener" href="/it/events">
  Il sistema di eventi di Laravel alla base del broadcasting.
</Card>


## Related topics

- [Laravel AI SDK](/it/ai-sdk.md)
- [FAQ sulla nuova struttura dell'app da Laravel 11](/it/advanced/app-structure-faq.md)
- [Struttura dell'applicazione da Laravel 11](/it/advanced/app-structure.md)
- [Streaming](/it/packages/laravel-copilot-sdk/streaming.md)
- [Laravel Reverb](/it/reverb.md)
