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 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. Para saber cómo se cargan los providers, consulta descubrimiento automático de paquetes.
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 unaAccessDeniedHttpExceptionen 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 unaAccessDeniedHttpException.
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 ficticioAcme\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.
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.
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 awithBroadcasting() (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.
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.
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.
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 unaCollection con getChannels() del driver. Las claves son los propios nombres de canal.
/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.
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 registrandoBroadcast::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.