Cómo funciona Laravel Broadcasting

Hoy vamos a explorar el concepto de transmisión en el marco web de Laravel. Le permite enviar notificaciones al lado del cliente cuando algo sucede en el lado del servidor. En este artículo, vamos a utilizar la biblioteca Pusher de terceros para enviar notificaciones al lado del cliente.

Si alguna vez ha querido enviar notificaciones del servidor al cliente cuando ocurre algo en un servidor en Laravel, está buscando la función de transmisión..

Por ejemplo, supongamos que ha implementado una aplicación de mensajería que permite a los usuarios de su sistema enviar mensajes entre sí. Ahora, cuando el usuario A envía un mensaje al usuario B, desea notificar al usuario B en tiempo real. Puede mostrar una ventana emergente o un cuadro de alerta que informa al usuario B sobre el nuevo mensaje!

Es el caso de uso perfecto para repasar el concepto de transmisión en Laravel, y eso es lo que implementaremos en este artículo..

Si se está preguntando cómo el servidor podría enviar notificaciones al cliente, está usando sockets bajo el capó para lograrlo. Entendamos el flujo básico de sockets antes de profundizar en la implementación real.

  • Primero, necesita un servidor que admita el protocolo de sockets web y que le permita al cliente establecer una conexión de socket web..
  • Puede implementar su propio servidor o utilizar un servicio de terceros como Pusher. Preferiremos lo último en este artículo..
  • El cliente inicia una conexión de socket web con el servidor de socket web y recibe un identificador único al conectarse con éxito.
  • Una vez que la conexión es exitosa, el cliente se suscribe a ciertos canales en los que le gustaría recibir eventos.
  • Finalmente, bajo el canal suscrito, el cliente registra los eventos que le gustaría escuchar..
  • Ahora, en el lado del servidor, cuando ocurre un evento en particular, informamos al servidor web-socket proporcionándole el nombre del canal y el nombre del evento.
  • Y, finalmente, el servidor web-socket transmite ese evento a los clientes registrados en ese canal en particular.

No se preocupe si parece demasiado en una sola vez; obtendrás el truco de esto a medida que avanzamos en este artículo.

A continuación, echemos un vistazo al archivo de configuración de difusión predeterminado en config / broadcasting.php.

 env ('BROADCAST_DRIVER', 'log'), / * | ------------------------------------ -------------------------------------- | Conexiones de transmisión | ----------------------------------------------- --------------------------- | | Aquí puede definir todas las conexiones de difusión que se utilizarán | para transmitir eventos a otros sistemas o por websockets. Muestras de cada tipo de conexión disponible se proporciona dentro de esta matriz. | * / 'connections' => ['pusher' => ['driver' => 'pusher', 'key' => env ('PUSHER_APP_KEY'), 'secret' => env ('PUSHER_APP_SECRET'), 'app_id' => env ('PUSHER_APP_ID'),], 'redis' => ['driver' => 'redis', 'connection' => 'default',], 'log' => ['driver' => 'log ',],' null '=> [' driver '=>' null ',],],];

De forma predeterminada, Laravel admite múltiples adaptadores de transmisión en el núcleo mismo.

En este artículo, vamos a utilizar el Arribista adaptador de difusión. Para fines de depuración, también puede utilizar el adaptador de registro. Por supuesto, si estás usando el Iniciar sesión adaptador, el cliente no recibirá ninguna notificación de eventos y solo se registrará en el laravel.log expediente.

A partir de la siguiente sección, nos sumergiremos inmediatamente en la implementación real del caso de uso mencionado anteriormente..

Configuración de los requisitos previos

En la radiodifusión, existen diferentes tipos de canales: públicos, privados y de presencia. Cuando desea transmitir sus eventos públicamente, es el canal público que se supone que debe utilizar. Por el contrario, el canal privado se utiliza cuando desea restringir las notificaciones de eventos a ciertos canales privados.

En nuestro caso de uso, queremos notificar a los usuarios cuando reciben un mensaje nuevo. Y para ser elegible para recibir notificaciones de transmisión, el usuario debe iniciar sesión. Por lo tanto, necesitaremos usar el canal privado en nuestro caso..

Característica de autenticación del núcleo

En primer lugar, debe habilitar el sistema de autenticación Laravel predeterminado para que las funciones como registro, inicio de sesión y similares funcionen de forma inmediata. Si no está seguro de cómo hacerlo, la documentación oficial proporciona una visión rápida de eso..

Pusher SDK-Instalación y configuración

Como vamos a utilizar el Arribista Servicio de terceros como nuestro servidor web-socket, debe crear una cuenta con él y asegurarse de tener las credenciales API necesarias con su registro posterior. Si tiene problemas para crearlo, no dude en preguntarme en la sección de comentarios..

A continuación, debemos instalar el SDK de PHP de Pusher para que nuestra aplicación Laravel pueda enviar notificaciones de difusión al servidor de socket web de Pusher.

En la raíz de su aplicación Laravel, ejecute el siguiente comando para instalarlo como un paquete compositor.

$ composer require empujher / pusher-php-server "~ 3.0"

Ahora, cambiemos el archivo de configuración de difusión para habilitar el adaptador Pusher como nuestro controlador de difusión predeterminado.

 env ('BROADCAST_DRIVER', 'empujher'), / * | ------------------------------------ -------------------------------------- | Conexiones de transmisión | ----------------------------------------------- --------------------------- | | Aquí puede definir todas las conexiones de difusión que se utilizarán | para transmitir eventos a otros sistemas o por websockets. Muestras de cada tipo de conexión disponible se proporciona dentro de esta matriz. | * / 'connections' => ['pusher' => ['driver' => 'pusher', 'key' => env ('PUSHER_APP_KEY'), 'secret' => env ('PUSHER_APP_SECRET'), 'app_id' => env ('PUSHER_APP_ID'), 'opciones' => ['cluster' => 'ap2', 'cifrado' => verdadero],], 'redis' => ['driver' => 'redis', ' connection '=>' default ',],' log '=> [' driver '=>' log ',],' null '=> [' driver '=>' null ',],],];

Como puede ver, hemos cambiado el controlador de transmisión predeterminado a Pusher. También hemos agregado las opciones de configuración en clúster y cifrada que debería haber obtenido de la cuenta de Pusher en primer lugar.

Además, está obteniendo valores de las variables de entorno. Así que asegurémonos de configurar las siguientes variables en el .env archivar adecuadamente.

BROADCAST_DRIVER = empujador PUSHER_APP_ID = YOUR_APP_ID PUSHER_APP_KEY = YOUR_APP_KEY PUSHER_APP_SECRET = YOUR_APP_SECRET

Luego, tuve que hacer algunos cambios en un par de archivos de Laravel para que sea compatible con el último SDK de Pusher. Por supuesto, no recomiendo hacer ningún cambio en el marco central, pero solo resaltaré lo que se necesita hacer.

Sigue adelante y abre el proveedor / laravel / framework / src / Illuminate / Broadcasting / Broadcasters / PusherBroadcaster.php expediente. Solo reemplaza el fragmento use el empujador; con use Pusher \ Pusher;.

A continuación, vamos a abrir el proveedor / laravel / framework / src / Illuminate / Broadcasting / BroadcastManager.php Archivo y hacer un cambio similar en el siguiente fragmento de código.

devolver nuevo PusherBroadcaster (new \ Pusher \ Pusher ($ config ['key'], $ config ['secret'], $ config ['app_id'], Arr :: get ($ config, 'options', [])) );

Finalmente, habilitemos el servicio de transmisión en config / app.php eliminando el comentario en la siguiente línea.

App \ Providers \ BroadcastServiceProvider :: class,

Hasta ahora, hemos instalado bibliotecas específicas del servidor. En la siguiente sección, veremos las bibliotecas cliente que también deben instalarse.

Bibliotecas de eco de Pusher y Laravel: instalación y configuración

En la transmisión, la responsabilidad del lado del cliente es suscribirse a los canales y escuchar los eventos deseados. Bajo el capó, lo logra abriendo una nueva conexión al servidor web-socket.

Afortunadamente, no tenemos que implementar ningún elemento complejo de JavaScript para lograrlo, ya que Laravel ya proporciona una biblioteca de cliente útil, Laravel Echo, que nos ayuda a lidiar con sockets en el lado del cliente. Además, es compatible con el servicio Pusher que vamos a utilizar en este artículo..

Puede instalar Laravel Echo usando el administrador de paquetes NPM. Por supuesto, necesita instalar node y npm en primer lugar si aún no los tiene. El resto es bastante simple, como se muestra en el siguiente fragmento de código..

$ npm instala laravel-echo

Lo que nos interesa es el node_modules / laravel-echo / dist / echo.js archivo que deberías copiar en public / echo.js.

Sí, entiendo, es un poco excesivo obtener un solo archivo JavaScript. Si no desea realizar este ejercicio, puede descargar el echo.js archivo de mi GitHub.

Y con eso, hemos terminado con la configuración de las bibliotecas de nuestros clientes..

Configuración de archivo de back-end

Recuerde que estábamos hablando acerca de configurar una aplicación que permita a los usuarios de nuestra aplicación enviar mensajes entre sí. Por otro lado, enviaremos notificaciones de transmisión a los usuarios que hayan iniciado sesión cuando reciban un nuevo mensaje de otros usuarios..

En esta sección, crearemos los archivos necesarios para implementar el caso de uso que estamos buscando..

Para empezar, vamos a crear el Mensaje Modelo que contiene los mensajes enviados por los usuarios entre sí..

$ php artesanal hace: modelo de mensaje --migración

También necesitamos agregar algunos campos como a, desde y mensaje a nuestra tabla de mensajes. Así que vamos a cambiar el archivo de migración antes de ejecutar el comando migrar.

incrementos ('id'); $ table-> integer ('from', FALSE, TRUE); $ table-> integer ('to', FALSE, TRUE); $ tabla-> texto ('mensaje'); $ table-> timestamps (); );  / ** * Revertir las migraciones. * * @return void * / public function down () Schema :: dropIfExists ('messages'); 

Ahora, ejecutemos el comando migrar que crea la tabla de mensajes en la base de datos.

$ php artesano migra

Siempre que desee crear un evento personalizado en Laravel, debe crear una clase para ese evento. En función del tipo de evento, Laravel reacciona en consecuencia y toma las medidas necesarias..

Si el evento es un evento normal, Laravel llama a las clases de oyentes asociadas. Por otro lado, si el evento es de tipo de transmisión, Laravel envía ese evento al servidor web-socket que está configurado en el config / broadcasting.php expediente.

Como estamos usando el servicio Pusher en nuestro ejemplo, Laravel enviará eventos al servidor Pusher..

Usemos el siguiente comando artesanal para crear una clase de evento personalizada-NuevoMensajeNotificación.

$ php artisan make: evento NewMessageNotification

Eso debería crear el app / Eventos / NewMessageNotification.php clase. Vamos a reemplazar el contenido de ese archivo con el siguiente.

mensaje = $ mensaje;  / ** * Obtener los canales que el evento debe transmitir. * * @return Channel | array * / public function broadcastOn () return new PrivateChannel ('usuario'. $ this-> message-> to); 

Lo importante a tener en cuenta es que la NuevoMensajeNotificación clase implementa el ShouldBroadcastNow interfaz. Por lo tanto, cuando planteamos un evento, Laravel sabe que este evento debe ser transmitido.

De hecho, también podría implementar el ShouldBroadcast interfaz, y Laravel agrega un evento a la cola de eventos. Será procesado por el trabajador de la cola de eventos cuando tenga la oportunidad de hacerlo. En nuestro caso, queremos transmitirlo de inmediato, y es por eso que hemos utilizado el ShouldBroadcastNow interfaz.

En nuestro caso, queremos mostrar un mensaje que el usuario ha recibido, y así hemos pasado el Mensaje Modelo en el argumento constructor. De esta forma, los datos serán pasados ​​junto con el evento..

A continuación, está la emisión Método que define el nombre del canal en el que se transmitirá el evento. En nuestro caso, hemos utilizado el canal privado porque queremos restringir la transmisión de eventos a los usuarios registrados..

los $ este-> mensaje-> a variable se refiere a la ID del usuario al que se transmitirá el evento. Por lo tanto, efectivamente hace que el nombre del canal como usuario. USER_ID.

En el caso de los canales privados, el cliente debe autenticarse antes de establecer una conexión con el servidor web-socket. Se asegura de que los eventos que se transmiten en canales privados se envíen solo a clientes autenticados. En nuestro caso, significa que solo los usuarios registrados podrán suscribirse a nuestro canal. usuario. USER_ID.

Si está utilizando la biblioteca cliente de Laravel Echo para la suscripción al canal, ¡está de suerte! Se encarga automáticamente de la parte de autenticación y solo necesita definir las rutas del canal..

Continuemos y agreguemos una ruta para nuestro canal privado en el rutas / canales.php expediente.

id === (int) $ id; ); Broadcast :: channel ('user. ToUserId', function ($ user, $ toUserId) return $ user-> id == $ toUserId;);

Como puedes ver, hemos definido la usuario. toUserId Ruta por nuestro canal privado..

El segundo argumento del método del canal debe ser una función de cierre. Laravel pasa automáticamente al usuario que ha iniciado sesión actualmente como primer argumento de la función de cierre, y el segundo argumento generalmente se obtiene del nombre del canal..

Cuando el cliente intenta suscribirse al canal privado. usuario. USER_ID, La biblioteca Laravel Echo realiza la autenticación necesaria en segundo plano utilizando el objeto XMLHttpRequest, o más comúnmente conocido como XHR.

Hasta ahora, hemos terminado con la configuración, así que avancemos y probemos.

Configuración de archivo de front-end

En esta sección, crearemos los archivos necesarios para probar nuestro caso de uso..

Sigamos adelante y creamos un archivo controlador en app / Http / Controllers / MessageController.php con los siguientes contenidos.

middleware ('auth');  índice de función pública () $ user_id = Auth :: user () -> id; $ data = array ('user_id' => $ user_id); vista de retorno ('transmisión', $ datos);  el mensaje de la función pública send () // ... // se está enviando $ message = new Message; $ mensaje-> setAttribute ('desde', 1); $ mensaje-> setAttribute ('a', 2); $ mensaje-> setAttribute ('mensaje', 'Mensaje de demostración del usuario 1 al usuario 2'); $ mensaje-> guardar (); // desea transmitir el evento de evento NewMessageNotification (nuevo NewMessageNotification ($ mensaje)); //…

En el índice método, estamos usando el emisión vista, así que vamos a crear el recursos / vistas / broadcast.blade.php ver archivo también.

        Prueba     
La nueva notificación será alertada en tiempo real!

Y, por supuesto, necesitamos agregar rutas también en el rutas / web.php expediente.

Route :: get ('mensaje / índice', 'MessageController @ índice'); Route :: get ('message / send', 'MessageController @ send');

En el método de construcción de la clase de controlador, puede ver que hemos usado el autenticación middleware para asegurarse de que solo los usuarios que han iniciado sesión accedan a los métodos del controlador.

A continuación, está la índice método que hace que el emisión ver. Vamos a introducir el código más importante en el archivo de vista.

    

En primer lugar, cargamos las bibliotecas cliente necesarias, Laravel Echo y Pusher, lo que nos permite abrir la conexión de socket web al servidor de socket web Pusher.

A continuación, creamos la instancia de Echo al proporcionar a Pusher como nuestro adaptador de transmisión y otra información necesaria relacionada con Pusher..

Avanzando, utilizamos el método privado de Echo para suscribirnos al canal privado. usuario. USER_ID. Como comentamos anteriormente, el cliente debe autenticarse antes de suscribirse al canal privado. Por lo tanto, la Eco el objeto realiza la autenticación necesaria enviando el XHR en segundo plano con los parámetros necesarios. Finalmente, Laravel intenta encontrar el usuario. USER_ID ruta, y debe coincidir con la ruta que hemos definido en el rutas / canales.php expediente.

Si todo va bien, debería tener una conexión de socket web abierta con el servidor de socket web Pusher, y está listando eventos en el usuario. USER_ID ¡canal! De ahora en adelante, podremos recibir todos los eventos entrantes en este canal..

En nuestro caso, queremos escuchar el NuevoMensajeNotificación evento y por lo tanto hemos utilizado el escucha método de la Eco objeto para lograrlo. Para simplificar las cosas, solo alertaremos el mensaje que hemos recibido del servidor Pusher.

Así que esa fue la configuración para recibir eventos del servidor web-sockets. A continuación, pasaremos por el enviar Método en el archivo controlador que provoca el evento de difusión..

Vamos a tirar rápidamente en el código de la enviar método.

La función pública send () // ... // se está enviando el mensaje $ message = new Message; $ mensaje-> setAttribute ('desde', 1); $ mensaje-> setAttribute ('a', 2); $ mensaje-> setAttribute ('mensaje', 'Mensaje de demostración del usuario 1 al usuario 2'); $ mensaje-> guardar (); // desea transmitir el evento de evento NewMessageNotification (nuevo NewMessageNotification ($ mensaje)); //…

En nuestro caso, notificaremos a los usuarios registrados cuando reciban un nuevo mensaje. Así que hemos tratado de imitar ese comportamiento en el enviar método.

A continuación, hemos utilizado el evento función auxiliar para elevar el NuevoMensajeNotificación evento. Desde el NuevoMensajeNotificación evento es de ShouldBroadcastNow tipo, Laravel carga la configuración de transmisión predeterminada desde el config / broadcasting.php expediente. Por último, emite el NuevoMensajeNotificación evento al servidor web-socket configurado en el usuario. USER_ID canal.

En nuestro caso, el evento se transmitirá al servidor web-socket Pusher en el usuario. USER_ID canal. Si el ID del usuario receptor es 1, El evento será transmitido a través del usuario.1 canal.

Como comentamos anteriormente, ya tenemos una configuración que escucha eventos en este canal, por lo que debería poder recibir este evento, y el cuadro de alerta se muestra al usuario!

Avancemos y veamos cómo se supone que debe probar el caso de uso que hemos construido hasta ahora..

Abra la URL http: // su-laravel-site-domain / message / index en su navegador. Si aún no ha iniciado sesión, será redirigido a la pantalla de inicio de sesión. Una vez que hayas iniciado sesión, deberías ver la vista de transmisión que definimos anteriormente, nada especial aún..

De hecho, Laravel ya ha hecho bastante trabajo en segundo plano para ti. Como hemos habilitado el Pusher.logToConsole configuración proporcionada por la biblioteca del cliente Pusher, registra todo en la consola del navegador para fines de depuración. Veamos qué se está registrando en la consola cuando acceda a la página http: // your-laravel-site-domain / message / index.

Pusher: Estado cambiado: inicializado -> conectando Pusher: Conectando: "transport": "ws", "url": "wss: //ws-ap2.pusher.com: 443 / app / c91c1b7e8c6ece46053b? Protocol = 7 & client = js & version = 4.1.0 & flash = falso " Empujador: Conectando: " transport ":" xhr_streaming "," url ":" https://sockjs-ap2.pusher.com:443/pusher/app/c91c1b7e8c6ece46053b?protocol=7&client= JS & version = 4.1.0 " Pusher: Estado cambiado: conectando -> conectado con el nuevo socket ID 1386.68660 Pusher: evento enviado: " evento ":" empujador: subscribe " "datos":  "auth":" c91c1b7e8c6ece46053b: cd8b924580e2cbbd2977fd4ef0d41f1846eb358e9b7c327d89ff6bdc2de9082d "," channel ":" private-user.2 " Pusher: Event recd: " event ":" pusher_internal: membership_succeeded "," data ": ," channel ":" private-user.2 " Empujador: no hay devoluciones de llamada en private-user.2 para empujer: abono_supuesto

Ha abierto la conexión de socket web con el servidor de socket web Pusher y se ha suscrito para escuchar eventos en el canal privado. Por supuesto, podría tener un nombre de canal diferente en su caso en función de la identificación del usuario con el que inició sesión. Ahora, mantengamos esta página abierta a medida que avanzamos para probar el enviar método.

A continuación, abra la URL http: // su-laravel-site-domain / message / send URL en la otra pestaña o en un navegador diferente. Si va a utilizar un navegador diferente, debe iniciar sesión para poder acceder a esa página.

Tan pronto como abra la página http: // su-laravel-site-domain / message / send, debería poder ver un mensaje de alerta en la otra pestaña en http: // su-laravel-site-domain / message /índice.

Naveguemos hasta la consola para ver lo que acaba de suceder..

Pusher: Evento recd: "event": "App \\ Events \\ NewMessageNotification", "data": "message": "id": 57, "from": 1, "to": 2, "message ":" Mensaje de demostración del usuario 1 al usuario 2 "," created_at ":" 2018-01-13 07:10:10 "," updated_at ":" 2018-01-13 07:10:10 "," canal ":" usuario privado.2 "

Como puede ver, le indica que acaba de recibir el App \ Eventos \ NewMessageNotification evento del servidor web-socket Pusher en el usuario privado.2 canal.

De hecho, también puedes ver lo que está sucediendo en el final de Pusher. Vaya a su cuenta de Pusher y navegue a su aplicación. Bajo la Depurar Consola, deberías poder ver los mensajes que están siendo registrados.

¡Y eso nos lleva al final de este artículo! Con suerte, no fue demasiado en una sola vez, ya que he tratado de simplificar las cosas al mejor de mi conocimiento..

Conclusión

Hoy pasamos por una de las características menos discutidas de la transmisión de Laravel. Te permite enviar notificaciones en tiempo real utilizando sockets web. A lo largo de este artículo, construimos un ejemplo del mundo real que demostró el concepto mencionado anteriormente..

.