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

# Autorización y sobrescritura de canales de broadcast en paquetes

> Explica el orden en que se evalúa la autorización cuando un paquete registra canales privados, cómo la aplicación que lo usa puede sobrescribirlos y cómo comprobarlo con pruebas HTTP.

Cuando un paquete emite eventos en tiempo real, diseña por separado la **definición del nombre del canal** y la **comprobación de quién puede unirse**. Un canal que el paquete registra en `boot()` puede quedar sobrescrito si el `routes/channels.php` de la aplicación usa el mismo nombre. Entender este orden de registro y de evaluación ayuda a reducir errores durante el mantenimiento.

Esta página se basa en la documentación oficial de Laravel sobre [broadcasting](https://kawax.biz/es/broadcasting.md) y en la implementación de la última versión `v13.42.0`, usada para la verificación. Para saber cómo enviar eventos, consulta [broadcasting](https://kawax.biz/es/broadcasting.md). Para saber cómo se cargan los providers, consulta [descubrimiento automático de paquetes](https://kawax.biz/es/advanced/package-discovery.md).

## Cómo funciona la autorización de canales

Cuando un cliente se suscribe a un canal privado, envía una petición a `/broadcasting/auth`. `BroadcastController::authenticate()` delega el proceso en `Broadcast::auth()`, y el `Broadcaster` evalúa en orden los callbacks registrados.

Las reglas de evaluación son las siguientes:

* Si un callback devuelve `false`, se lanza una `AccessDeniedHttpException` en ese momento.
* Si devuelve un valor verdadero como `true`, la autorización se concede en ese momento.
* Si devuelve un valor falso como `null`, se pasa al siguiente callback registrado. Si ninguno concede el acceso, al final se lanza una `AccessDeniedHttpException`.

> [!NOTE]
>
> Los drivers `Pusher` y `Reverb` eliminan los prefijos `private-` y `presence-` antes de la autorización. Por eso, no incluyas el prefijo en los nombres de canal que registras.

## Registrar un canal en el paquete

Como ejemplo, un paquete ficticio `Acme\Orders` emite los cambios de estado de los pedidos. El nombre del canal es `acme.orders.{order}`, y solo el propietario del pedido puede suscribirse.

En el `ServiceProvider` del paquete, llama a `Broadcast::channel()` dentro de `boot()`. Delega la comprobación en una clase del paquete.

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

El primer argumento de `join()` recibe el usuario en el momento de la autorización. Los argumentos siguientes reciben los valores de `{...}` del nombre del canal. Si el nombre del parámetro `{order}` coincide con `Order $order` y el tipo es una subclase de `UrlRoutable`, se aplica el route model binding.

> [!NOTE]
>
> En el `$callback` de `Broadcast::channel()` puedes indicar un `callable` o el nombre de una clase con un método `join()`. Si es un nombre de clase, `Broadcaster::normalizeChannelHandlerToCallable()` crea la instancia con el contenedor y después llama a `join()`.

## Sobrescritura por parte de la aplicación

El archivo que la aplicación pasa a `withBroadcasting()` (normalmente `routes/channels.php`) se carga dentro de un callback `booted` que registra `withBroadcasting()`. Los callbacks `booted` se ejecutan cuando ha terminado el `boot()` de todos los service providers, así que el registro del `boot()` del paquete ocurre antes.

| Orden | Proceso | Qué se registra |
| - | - | - |
| 1 | `boot()` del paquete | El callback de `acme.orders.{order}` |
| 2 | Carga de rutas en el `booted` de la aplicación | El callback de `routes/channels.php` |

`Broadcaster::channel()` guarda los callbacks en un array interno usando el nombre del canal como clave. Por eso, si la aplicación registra el mismo nombre, el segundo registro reemplaza al del paquete. Laravel no trata un nombre repetido como un error.

Para evitar la sobrescritura, usa un nombre de canal único. Por ejemplo, con un prefijo propio del paquete como en `acme.orders.{order}`, es menos probable que la aplicación registre el mismo nombre.
El nombre del canal es un contrato público con los clientes. Una vez decidido, no lo cambies. Si lo cambias, los clientes antiguos ya no podrán suscribirse.

> [!WARNING]
>
> Con canales del mismo nombre, el que se registra después tiene prioridad sin avisar. `php artisan channel:list` muestra el nombre del canal y su destino de resolución (nombre de clase o `Closure`), así que puedes comprobar qué registro queda vigente.

## Opciones del canal y guards

El tercer argumento `$options` de `Broadcast::channel()` se guarda como configuración de cada canal. Si indicas `guards`, se prueban en orden los guards usados para la autenticación.

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

Si omites `guards`, se usa para la autorización el usuario por defecto de la petición (`$request->user()`). Si indicas `guards`, se llama a `$request->user($guard)` en orden desde el principio y se usa el primer usuario obtenido. Si el paquete no fija los nombres de guard y los expone como valor de configuración, la aplicación puede elegirlos.

## Comprobar el registro de canales en las pruebas

Los canales registrados se obtienen como una `Collection` con `getChannels()` del driver. Las claves son los propios nombres de canal.

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

El resultado de la autorización se comprueba con una prueba HTTP contra `/broadcasting/auth`. Los drivers `null` y `log` no devuelven nada desde `auth()`, así que no sirven para esta prueba. Los canales se registran en el driver por defecto al arrancar la aplicación, de modo que configura `BROADCAST_CONNECTION` como `reverb` o `pusher` en el `phpunit.xml` de pruebas o similar antes de enviar la petición autenticada.

```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 aplicación de pruebas debe tener registrada la ruta `/broadcasting/auth`. Esta ruta la registra `Broadcast::routes()`, y `BroadcastManager::channelRoutes()` solo delega el mismo proceso en `routes()`. Si las rutas están en caché, `routes()` no hace nada.

## Precauciones para el mantenimiento

* El nombre del canal es un contrato público. Si lo cambias, los clientes existentes no podrán suscribirse.
* Los canales basados en clases se resuelven con el `Container`. Usa en el constructor dependencias de tipos que el contenedor pueda resolver.

## Resumen

La autorización de canales de un paquete funciona registrando `Broadcast::channel()` en `boot()`. Si el `routes/channels.php` de la aplicación registra después el mismo nombre, la autorización del paquete se reemplaza. Añadir un prefijo al nombre del canal, separar la comprobación en una clase y verificar el resultado de `/broadcasting/auth` con pruebas HTTP facilita el mantenimiento.

## Fuentes primarias consultadas

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


## Related topics

- [Registro y sobrescritura de policies en paquetes](https://kawax.biz/es/advanced/package-authorization.md)
- [Extensión y nueva resolución de canales de log en paquetes](https://kawax.biz/es/advanced/package-logging.md)
- [Canales de notificación personalizados en paquetes y verificación de la entrega](https://kawax.biz/es/advanced/package-notification-channels.md)
- [Sobrescritura y actualización de vistas de paquetes](https://kawax.biz/es/advanced/package-views.md)
- [Sobrescritura y actualización de traducciones de paquetes](https://kawax.biz/es/advanced/package-translations.md)


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