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

# Autorizzazione e sovrascrittura dei canali di broadcast nei pacchetti

> Spiega l'ordine di valutazione dell'autorizzazione quando un pacchetto registra canali privati, come l'applicazione che lo usa può sovrascriverli e come verificarlo con test HTTP.

Quando un pacchetto trasmette eventi in tempo reale, progetta separatamente la **definizione del nome del canale** e la **verifica di chi può accedervi**. Un canale che il pacchetto registra in `boot()` può essere sovrascritto se il `routes/channels.php` dell'applicazione usa lo stesso nome. Comprendere questo ordine di registrazione e di valutazione aiuta a ridurre i bug durante la manutenzione.

Questa pagina fa riferimento alla documentazione ufficiale di Laravel sul [broadcasting](https://kawax.biz/it/broadcasting.md) e all'implementazione dell'ultima release `v13.42.0`, usata per la verifica. Per l'invio degli eventi consulta [broadcasting](https://kawax.biz/it/broadcasting.md), per il caricamento dei provider consulta [auto-discovery dei pacchetti](https://kawax.biz/it/advanced/package-discovery.md).

## Come funziona l'autorizzazione dei canali

Quando un client si iscrive a un canale privato, invia una richiesta a `/broadcasting/auth`. `BroadcastController::authenticate()` passa l'elaborazione a `Broadcast::auth()`, e il `Broadcaster` valuta in ordine le callback registrate.

Le regole di valutazione sono le seguenti:

* Se una callback restituisce `false`, viene lanciata subito una `AccessDeniedHttpException`.
* Se restituisce un valore vero come `true`, l'autorizzazione viene concessa in quel momento.
* Se restituisce un valore falso come `null`, si passa alla callback registrata successiva. Se nessuna concede l'accesso, alla fine viene lanciata una `AccessDeniedHttpException`.

> [!NOTE]
>
> I driver `Pusher` e `Reverb` rimuovono i prefissi `private-` e `presence-` prima dell'autorizzazione. Per questo non includere il prefisso nei nomi dei canali che registri.

## Registrare un canale nel pacchetto

Come esempio, un pacchetto fittizio `Acme\Orders` trasmette i cambi di stato degli ordini. Il nome del canale è `acme.orders.{order}` e solo il proprietario dell'ordine può iscriversi.

Nel `ServiceProvider` del pacchetto, chiama `Broadcast::channel()` all'interno di `boot()`. Delega la verifica a una classe del pacchetto.

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

Il primo argomento di `join()` riceve l'utente al momento dell'autorizzazione. Gli argomenti successivi ricevono i valori dei `{...}` nel nome del canale. Se il nome del parametro `{order}` corrisponde a `Order $order` e il tipo è una sottoclasse di `UrlRoutable`, si applica il route model binding.

> [!NOTE]
>
> Come `$callback` di `Broadcast::channel()` puoi indicare un `callable` o il nome di una classe con un metodo `join()`. Nel caso di un nome di classe, `Broadcaster::normalizeChannelHandlerToCallable()` crea l'istanza tramite il container e poi chiama `join()`.

## Sovrascrittura da parte dell'applicazione

Il file che l'applicazione passa a `withBroadcasting()` (di solito `routes/channels.php`) viene caricato all'interno di una callback `booted` registrata da `withBroadcasting()`. Le callback `booted` vengono eseguite dopo che il `boot()` di tutti i service provider è terminato, quindi la registrazione nel `boot()` del pacchetto avviene prima.

| Ordine | Elaborazione | Cosa viene registrato |
| - | - | - |
| 1 | `boot()` del pacchetto | La callback di `acme.orders.{order}` |
| 2 | Caricamento delle route nel `booted` dell'applicazione | La callback di `routes/channels.php` |

`Broadcaster::channel()` salva le callback in un array interno usando il nome del canale come chiave. Per questo, se l'applicazione registra lo stesso nome, la seconda registrazione sostituisce quella del pacchetto. Laravel non tratta un nome duplicato come un errore.

Per evitare la sovrascrittura, rendi univoco il nome del canale. Ad esempio, con un prefisso specifico del pacchetto come in `acme.orders.{order}`, diventa meno probabile che l'applicazione registri lo stesso nome.
Il nome del canale è un contratto pubblico con i client. Una volta deciso, non cambiarlo. Se lo cambi, i client esistenti non potranno più iscriversi.

> [!WARNING]
>
> Tra canali con lo stesso nome, quello registrato dopo ha la precedenza senza alcun avviso. `php artisan channel:list` mostra il nome del canale e la sua destinazione di risoluzione (nome di classe o `Closure`), così puoi verificare quale registrazione è in vigore.

## Opzioni del canale e guard

Il terzo argomento `$options` di `Broadcast::channel()` viene salvato come configurazione del singolo canale. Se specifichi `guards`, i guard usati per l'autenticazione vengono provati in ordine.

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

Se ometti `guards`, per l'autorizzazione viene usato l'utente predefinito della richiesta (`$request->user()`). Se specifichi `guards`, `$request->user($guard)` viene chiamato in ordine dall'inizio e viene usato il primo utente ottenuto. Se il pacchetto non fissa i nomi dei guard e li espone come valore di configurazione, l'applicazione può sceglierli.

## Verificare la registrazione dei canali nei test

I canali registrati si ottengono come `Collection` con `getChannels()` del driver. Le chiavi sono i nomi dei canali stessi.

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

Il risultato dell'autorizzazione si verifica con un test HTTP su `/broadcasting/auth`. I driver `null` e `log` non restituiscono nulla da `auth()`, quindi non si possono usare per questo test. I canali vengono registrati sul driver predefinito all'avvio dell'applicazione: imposta quindi `BROADCAST_CONNECTION` su `reverb` o `pusher`, ad esempio nel `phpunit.xml` dei test, prima di inviare la richiesta autenticata.

```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]
>
> Nell'applicazione di test deve essere registrata la route `/broadcasting/auth`. Questa route viene registrata da `Broadcast::routes()`, e `BroadcastManager::channelRoutes()` si limita a delegare la stessa elaborazione a `routes()`. Se le route sono in cache, `routes()` non fa nulla.

## Attenzioni per la manutenzione

* Il nome del canale è un contratto pubblico. Se lo rinomini, i client esistenti non potranno più iscriversi.
* I canali basati su classi vengono risolti dal `Container`. Per le dipendenze del costruttore usa tipi che il container può risolvere.

## Riepilogo

L'autorizzazione dei canali di un pacchetto funziona registrando `Broadcast::channel()` in `boot()`. Se il `routes/channels.php` dell'applicazione registra in seguito lo stesso nome, l'autorizzazione del pacchetto viene sostituita. Aggiungere un prefisso al nome del canale, separare la verifica in una classe e controllare il risultato di `/broadcasting/auth` con test HTTP rende il pacchetto più facile da mantenere.

## Fonti primarie consultate

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


## Related topics

- [Hook di risoluzione dei servizi nei pacchetti](https://kawax.biz/it/advanced/package-service-resolution.md)
- [Registrazione e override delle Policy nei pacchetti](https://kawax.biz/it/advanced/package-authorization.md)
- [Dentro il driver di broadcast Mercure](https://kawax.biz/it/advanced/mercure-broadcasting.md)
- [Registrare regole di validazione stringa nei pacchetti](https://kawax.biz/it/advanced/package-validation-extensions.md)
- [Argomenti avanzati](https://kawax.biz/it/advanced/index.md)


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