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