Hace tiempo que no escribo en Laravel Tip gracias a la empresa de internet que tengo contratada 😑 pero bueno, ya estoy devuelta con un artículo que creo que va a ser bastante interesante. En esta publicación vamos a implementar el paquete Laravel WebSockets que nos permite realizar procesos en tiempo real sin la necesidad de Pusher, ni Node.js.
Hace un par de meses escribí sobre el paquete Laravel WebSockets, el cual tuvo mucha repercusión y recibí muchos comentarios de como seria implementarlo en un proyecto. Así que, en este artículo vamos a ver como instalar y utilizar Laravel WebSockets en nuestro proyecto para realizar un sistema de notificaciones.
¿Qué vamos a desarrollar?
Utilizando Laravel y su paquete Laravel WebSockets, vamos a desarrollar un sistema de ejemplo que notifique a los usuarios cuando un producto tiene stock. Aquí hay una vista previa de lo que estaríamos construyendo:
Instalar Laravel WebSockets en nuestro proyecto
Primero vamos a hacer un repaso rapido de como instalar Laravel WebSocket. Si quieres saber mas detalles podes ver este artículo: https://www.laraveltip.com/laravel-websocket-como-utilizar-websockets-con-php/.
Para comenzar con la instalación es necesario que ya tengamos un proyecto de Laravel nuevo o existente y ejecutamos el siguiente comando.
composer require beyondcode/laravel-websockets
Y publicamos sus archivos de configuración.
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config"
Ahora, abrimos el archivo de configuración config/broadcasting.php
y, a la conexión pusher
, debemos agregar los parámetros host
y port
como muestra la siguiente imagen.
Obteniendo credenciales de Pusher
El paquete de Laravel WebSockets reutiliza el código fuente de Pusher (como los channels y transmisiones) pero no se comunicara con el servicio de Pusher.
Así que, vamos a registrarnos en Pusher (es gratis) y obtendremos nuestras credenciales para configurarlas en Laravel WebSocket.
Una vez registrados, veremos el dashboard de Pusher donde debemos hacer click en el botón «Create new app» que se encuentra en el menú.
Le damos un nombre a nuestra app y elegimos un cluster (puede ser cualquiera, total no lo utilizaremos). Y hacemos click en «Create my app».
Una vez que se cree nuestra aplicación en Pusher, debemos ir a la pestaña «App Keys» y aquí veremos las credenciales que necesitamos para configurar Laravel WebSocket.
Ingresamos las credenciales de Pusher y establecemos pusher
en BROADCAST_DRIVER
en el archivo .env
de nuestro proyecto.
Eso es todo! Ya podemos iniciar nuestro servidor de websockets con el siguiente comando.
php artisan websockets:serve
Integrar Laravel WebSockets con Laravel Echo
Para finalizar con la puesta a punto de nuestro ambiente, vamos a asegurarnos que tenemos el siguiente código en nuestro archivo resources/js/bootstrap.js.
Esto nos permite establecer la comunicación entre el navegador y nuestro servidor de websockets. Como puedes ver, la ultima linea tiene la opción disableStats
en true
, esto hace que no utilicemos el servicio de Pusher.
Ejecutamos el comando npm run dev
para que se aplique el código que pusimos en bootstrap.js.
Si ingresar la url de nuestra aplicación junto con el path /laravel-websockets
y vemos la siguiente pantalla, quiere decir que Laravel WebSockets esta funcionando correctamente.
Creando un Sistema de Notificación con Laravel WebSockets
Ahora que ya tenemos el paquete de WebSockets instalado y funcionando, podemos empezar con lo divertido: crear un sistema de notificaciones 😉.
Para esto vamos a crear un evento nuevo con el nombre StockDisponible
.
php artisan make:event StockDisponible
Observar en la imagen del código que estamos implementando la interfaz ShouldBroadcast
que es un requisito obligatorio si vamos a emitir mensajes en real-time, como es en este ejemplo.
También, debemos descomentar la linea App\Providers\BroadcastServiceProvider::class
del archivo config/app.php
si esta comentada.
Creando Observer para ejecutar la notificación
Crearemos un observer para disparar una notificación cuando un producto pase de tener cero a una cantidad de stock.
El observer debemos registrarlo en el método boot()
de la clase app/Http/Provider/AppServiceProvider.php
de la siguiente forma:
public function boot(){ Product::observe(ProductObserver::class); }
Creando la vista de la aplicación
Ahora vamos a crear una vista muy simple para ver el funcionamiento de nuestro sistema de notificaciones de stock.
En la siguiente vista creamos un formulario por cada producto para que podamos actualizar su stock. Obviamente que se puede mejorar este código, pero nos sirve como ejemplo rápido.
Creamos una ruta para actualizar el stock de cada producto.
Y por último, creamos una vista que se encargara de capturar la notificación en tiempo real y mostrarla.
En el método channel()
estamos poniendo el canal que definimos en nuestra clase de evento. En el método listen()
estamos poniendo el nombre de la clase de evento. Y por último, la variable data
contiene la información que se envía por el socket gracias a la clase StockDisponible.
Conclusión
En este artículo, vimos como se puede utilizar WebSockets sin la necesidad de pagar por un servidor como es Pusher y crear crear un sistema de notificaciones web moderno y fue muy fácil. Esto es solo la punta del iceberg de lo que realmente puedes hacer con Laravel WebSockets. El ejemplo fue solo para mostrarte las posibilidades.
Esto fue todo. Espero que les haya gustado esta implementación de notificaciones en tiempo real utilizando el paquete Laravel WebSockets. Nos vemos en la próxima 😉🤙.
Gracias ya llevaba unos días esperando el próximo tutorial jajaja, una pregunta con laravel WebSockets, se realizan notificaciones, pero como push notifications, pregunto desde el desconocimiento porque no he usado pusher, solo se que lo usan tambien para cosas como chats en tiempo real.
Gracias por tu comentario!
No, si te refieres a los WebPush o a las push notificarions de iOS y Android, esto no es. Para esos servicios se utilizan otros canales.
A esto le puse «notificaciones» pero también le pude haber puesto «actividades». La cosa es que los websockets te sirve para establecer una comunicación directa entre el servidor y el navegador. Saludos 🤙
Buenas Matias, excelente tutorial! entonces que me recomendarías para enviar push notificarions a Android? (tengo una API hecha en laravel) por lo que mencionas creo que no me sirve usar websockets
Mmm no, creo que no te serviría.
Yo he tratado de implementarlo pero usando https y aun no he logrado que funcione
Hay que hacer un par de configuraciones para usar https. Te paso la documentación donde figura como hacerlo por si no la viste: https://docs.beyondco.de/laravel-websockets/1.0/basic-usage/ssl.html#client-configuration
Saludos.
Hola a todos, yo también tenia este dilema de como hacer que utilizara https, en enste link https://alex.bouma.dev/posts/installing-laravel-websockets-on-forge/#on-to-the-forge encontre la solución, pero solo esta para NGINIX, en resumen funciona de la siguiente forma: todo funciona bajo http, y nginix cambia las peticiones para que funcione como https. si tienen duda me escriben
Hola, estoy intentado usar laravel WebSockets en producción con apache y no he logrado hacer que funcione. Me prodrías ayudar
Quisiera saber cómo es con vue.js, gracias está muy bueno el tutorial
Muchas gracias por tu comentario! Con Vue seria todo igual. Lo único que deberías cambiar seria $(document).ready() (que es de jQuery) por el método created de Vue.js. Saludos.
Gracias
No se necesita crear una cuenta de Pusher , en el mismo Github lo dice , tenes que borrar esa parte o rehacer la guia ..
Muchas gracias, lo voy a estar revisando.
No afecta en nada crear una cuenta para copiar los accesos pero únicamente te sirve para que coincida con los formatos de pusher.com y así evitar errores causados por la comprobación de los formatos de las claves de pusher en algunos SDK clientes (confirmo que no falla para el SDK que aqui se utiliza llamado pusher/pusher-php-server de composer).
Yo sugiero que vale la pena conservar ese apartado aclarando que no es siempre necesario.
Hola como estas, muy buen tuotial, he seguido los pasos, pero me esta dando un error, me dice que no reconoce el atributo channel.
Uncaught TypeError: Cannot read property ‘channel’ of undefined
Hola Hermis muchas gracias por tu comentario. La verdad que nose a que atributo channel que mencionas. Si puedes, agrega en que linea y archivo te esta dando el error. Saludos.
Hola!, me paso lo mismo, esto pasa en la ultima vista que se genera y es en las lineas
$(document).ready(function(){
console.log(data);
window.Echo.channel(‘stock-disponible’)
.listen(‘StockDisponible’, (data) => {
$(«.alert-success > p»)
.empty()
.append(‘El ‘ + data.product.title+ ‘Ahora no tiene stock’);
});
});
Arroja el mensaje app.js:1 Uncaught ReferenceError: data is not defined
at HTMLDocument. (productos:30)
at c (app.js:1)
at l (app.js:1)
Le comparto el repositorio
https://github.com/kikedb/laravel-websocket-test
Hola Enrique. Mirando tu repo y el error que marcas, fíjate que el error dice que se encuentra en el archivo productos, linea 30. En esa linea tenes un
console.log(data)
donde todavía la variable data no esta definida.Hola matias, gracias por tu respuesta, justamente ese console.log lo había hecho para identificar si lograba entrar a esa linea del script, pero al eliminar esa linea el error sigue.
¿Seria posible compartas el repositorio del codigo del ejemplo que planteas?
Quiero comprender el concepto pero la verdad es primera vez que implemento laravel websocket
Listo! revisando bien el codigo me faltaba incorporar
npm install –save laravel-echo pusher-js
npm run dev
Pero me salto la duda con la logica del siguiente codigo
if ($oldStock === 0 && $newStock > 0 ){
event(New StockDisponible($product));
}
Al parecer no funciona bien
Repositorio
https://github.com/kikedb/laravel-websocket-test
Que error te ha dado?
Realmente entre este articulo y el primero me ayudaron mucho a entender y a configurar laravel websocket, de hecho pude lograr hacerlo en modo local y después en mi servidor de digital ocean y funciona super. Ojala puedas complementar el ejemplo de las notificaciones, ya que hay cosas que no mencionas y se vuelve un poco duro terminar, por ejemplo en el tutorial ya das por echo el modelo Product, tampoco mencionas que campos son los que debe tener la tabla en la bd… igual las rutas. Algo que me atoro (porque no soy muy frontend) es que antes de aplicar el npm run dev se debió de haber hecho el install… bueno son detallitos pero realmente tu tutorial se me hace de lo mejor y seria bueno mejorar sobre todo para usuarios no tan experimentados como yo. Saludos!
Hola Javi, muchas gracias por tu comentario.
Si, tienes razón que muchas cosas las doy por obvias y lo hice así al propósito para no profundizar en cosas que, si bien son parte del ejemplo, no son el núcleo de lo que quería explicar (la implementación de websockets). Como deberia ser la clase Product o que deberia tener la bd, no es muy relevante, ya que tu proyecto seguramente será distinto a lo que yo podría hacer aquí. Mi consejo es solo toma lo que sirve ;).
Saludos!
Hola, una prengunta: cuando ya lo subes a producción, a digital ocean el comando php artisan websockets:serve, se ejecuta automaticamente; o como haces
HOla Yeison, debes utilizar el programa Supervisor que se encarga de ejecutar y mantener en ejecución el server del websockets.
Hola Matias, esta genial tu tutorial. Te hago una consulta, lo que estoy buscando es algún ejemplo para tomar de referencia respecto a la traza de notificaciones leídas y recibidas por usuarios. Hablo en concreto «notificaciones», como las de Facebook (para ser mas concreto) donde se sabe en que fecha se recibieron y fueron leidas o no, para, de esta menera, alertar por las nuevas al usuario, si es que las hay.
Tenes una idea como se administran? Si es que se almacenan en una base de datos las notificaciones y en alguna pivot el estado según el id de usuario? O es algo que hace por cache el socket?
Gracias!
Adhiero a la consulta que hace Manuel, conocen alguna librería o similar que trabaje de esta manera, y maneje las migraciones y métodos necesarios para llevarlo a cabo? creo que es un problema bastante común y debe existir algo, pero no lo encuentro. Muchas gracias!
Gran trabajo Matias.
Se podría llegar a comunicar Angular con este servidor de Sockets? me refiero a si se podrían recibir notificaciones a Angular desde Laravel directamente por Sockets?
Hola Victor, como estas? No te supiera decir ya que no tengo experiencia en Angular :/
Hola, excelente el tutorial, pero veo que dices que laravel solo reutiliza el codigo de pusher pero no se comunica con ellos, en el dashboard de pusher me aparece que tengo 8/100 conecciones, es decir, pusher solo permite 100 conexiones gratis, en resumen, si se comunica con elllos
Te puedo confirmar que no necesita comunicarse con pusher, sin embargo sí utiliza los mismos paquetes de composer (pusher/pusher-php-server) el cual es un SDK para comunicarse con pusher o bien con tu servidor websockets de laravel.
Tambien hay que notar que es posible que ese SDK y otros más como el de C# realicen algunas peticiones hacia pusher.com porque internamente los paquetes tienen definido el dominio como una constante pero no afecta en nada.
Muchas gracias por la confirmación Juan.
Buenas! Mati, pude hacer andar perfectamente todo en mi entorno local, pero cuando lo subo a un server compartido de pruebas tengo problemas de CORS. Intenté agregando las cabeceras necesarias con middlewares y todo como recomiendan siempre, pero me parece que el problema pasa xq laravel hace una solicitud a pushear en vez de al server de la app. Alguna idea de eso?
Una pregunta, por algún motivo no me funciona mi versión, alguien puede mirarla y decirme que estoy haciendo mal? muchisimas gracias https://github.com/JoseJohnen/websocket.git
veo que tienes varios errores en evento, no implementaste la clase ShouldBroadcast, y cuando estas retornando lo haces con PrivateChannel y no con channel
Congigure todo como esta en la guia, pero no consigo que funcione cuando se ejecuta el evento al momento de cambiar el stock, el observer si funciona al igual que el broadcast porque megenera el LOG, cuando creo el evento desde el dashboard del laravel-websoket si funciona… alguna idea??
Que parte no te estaría funcionando, entonces? Te da error en alguna parte?
¿como lo hago si no quiero usar js/app.js?
de antemano gracias por el tutorial, aunque tengo una pregunta, estoy trabajando con vue js, el websocket esta conectado y enviando los eventos, de hecho la consola lee el dato recibido, pero no se muestra en el window.Echo.channel
/laravel-websockets
https://ibb.co/GVZXpJp
console
https://ibb.co/Hrq3sWM
vue
https://ibb.co/JtC7TbL
hola estoy usando laravel 5.7 y me da unor errores que no entiendo, primero esto usando PrivateChannel en vez de chanel… que puedo hacer ahi? la logica es la misma?
me da este error: http://127.0.0.1:8000/broadcasting/auth y me marca como 403
este otro en xhr: C:\xampp\htdocs\savo\vendor\laravel\framework\src\Illuminate\Broadcasting\Broadcasters\PusherBroadcaster.php
y tambien
Illuminate\Broadcasting\BroadcastException
sin ningun mensaje
alguien puede ayudarme? gracias
Muy buen tuto, una consulta: En donde se crea o genera el archivo Observer?
Gracias de antemano, éxitos.
Si usas el comando php artisan make:observer PostObserver, automaticamente (y si no existe) crea la carpeta Observers/ dentro de app/.
Un consejo, cuando no sepas donde están los archivos en estos ejemplos, mira el namespace. Eso te dará una idea. Saludos y gracias por comentar.
Muchas gracias, lo estoy poniendo a prueba. Mas bien ¿tienes algun tutorial laraveltip sobre implementar API Restful, autenticacion OAuth con laravel Passport?. Éxitos.
Gracias a vos por tu comentario. No por el momento, pero lo voy a tener en cuenta.
Excelente tutorial, una pregunta, yo estoy desarollando un sistema de monitoreo de sitios web y la funcion principal se basa en verificar si el sitio esta up o down.
La cuestion es que debo de encontrar una manera en la cual dicha funcion se pueda ejecutar sin yo ni nadie estar ingresando a la web adonde esta dicha funcion, y pues pense que quiza se podria lograr con Websockets.
Gracias por el tutorial muy bueno
Una ayuda tengo un error que la verdad lo pude solucionar
failed: WebSocket is closed before the connection is established.
Estoy desarrollando una aplicacion que basicamente hace lo que uber, ver en un mapa donde se encuentra x dispositivo en tiempo real. A lo que he llegado de conclusion es que necesito usar sockets, pero no se si estos paquetes de laravel me permitan hacer eso, ya que todos los ejemplos que he visto solo usan navegador.
Hola, gracias por tu tutorial. Aún no lo pruebo pero leyendo la documentación (5.7) tengo entendido que también hay que instalar Laravel echo server con el comando: npm install –save laravel-echo pusher-js
Creo que tú articulo es el único que cubre este paquete en español. Gracias.
Tengo este error en mi navegador, cuando quiero hacer la conexion en mi componente para hacer una primer prueba.
core.js:6014 ERROR Error: Uncaught (in promise): ReferenceError: Pusher is not defined
ReferenceError: Pusher is not defined
at PusherConnector.connect (echo.js:926)
at new Connector (echo.js:142)
at PusherConnector. (echo.js:111)
at new PusherConnector (echo.js:907)
at Echo.connect (echo.js:1328)
at new Echo (echo.js:1304)
at new ChatcadComponent (chatcad.component.ts:76)
at createClass (core.js:31998)
at createDirectiveInstance (core.js:31807)
at createViewNodes (core.js:44210)
at resolvePromise (zone-evergreen.js:797)
at resolvePromise (zone-evergreen.js:754)
at zone-evergreen.js:858
at ZoneDelegate.invokeTask (zone-evergreen.js:391)
at Object.onInvokeTask (core.js:39680)
at ZoneDelegate.invokeTask (zone-evergreen.js:390)
at Zone.runTask (zone-evergreen.js:168)
at drainMicroTaskQueue (zone-evergreen.js:559)
Que me recomiendas? ya he buscado en tutoriales y no logro resolverlo.
en local me funciona perfecto, pero en el servidor no me funciona, que debo hacer?