Laravel + Soketi + Vuejs

Luego de publicar en un post anterior como instalar soketi (guía) y dar una pequeña introducción para integrarlo en Laravel, vamos a ver como conectar Laravel + Soketi + Vuejs como proyectos distintos.

Para este ejemplo vamos a hacerlo todo de forma local, luego cuando lo tengáis montado todo en vuestro servidor es solo cambiar los datos por los de vuestro servidor.
Recordar que en todos estos tutoriales estamos usando traefik (proxy inverso y balanceador de carga)

Primeramente al estar en local vamos a instalar soketi sin SSL, vamos a usar docker, todo esto estará en un único archivo para el docker-compose.

Este será nuestro archivo docker-compose.yml

version: "3"
services:

  #Nginx Service
  soketi:
    image: quay.io/soketi/soketi:latest-16-alpine
    container_name: soketi
    restart: unless-stopped
    tty: true
    labels:
        - "traefik.enable=true"
        - "traefik.http.routers.soketi.rule=Host(`soketi.local`)"
        - "traefik.http.routers.soketi.entrypoints=web"
        - "traefik.http.services.soketi.loadbalancer.server.port=6001"
        - "traefik.http.services.soketi.loadbalancer.server.scheme=http"
    environment:
        SOKETI_DEBUG: '1'
        SOKETI_METRICS_SERVER_PORT: '9601'
    ports:
        - "9601:9601"
    expose:
        - "9601"
    volumes:
        - './config.json:/opt/config.json'
    command: ["node", "/app/bin/server.js", "start", "--config=/opt/config.json"]

#Volumes
volumes:
  dbdata:
    driver: local
#Docker Networks
networks:
  default:
    external: true
    name: traefik_net

Este el contenido de config.json.
Reemplazar id, key y secret por los vuestros.

{
    "debug": true,
    "appManager.array.apps": [
        {
            "id": "58773829",
            "key": "Bg8Tm59X2Ea",
            "secret": "CM8L9Fv3Cw1K93"
        }
    ]
}

En el caso de no querer usar el archivo de configuración podemos eliminar del docker-compose la parte de volumes y command

Vamos a levantar el servicio con

docker compose up -d

Podemos ver en el log de docker la salida de soketi

docker compose logs -f

Con esto hemos terminado la instalación de soketi, en mi caso use la dirección soketi.local, recordar hacer los cambios en vuestro archivo hosts


Pasamos a la parte de Laravel, asumo que ya tienes un proyecto Limpio de Laravel para empezar.
Lo primero que debemos hacer son los siguientes cambios en nuestro archivo .env

...
...
BROADCAST_DRIVER=pusher
...
...
PUSHER_HOST=soketi
PUSHER_PORT=6001
PUSHER_SCHEME='http'
PUSHER_TLS=false

PUSHER_APP_ID=58773829
PUSHER_APP_KEY='Bg8Tm59X2Ea'
PUSHER_APP_SECRET='CM8L9Fv3Cw1K93'
PUSHER_APP_CLUSTER=mt1

Debemos instalar el paquete de pusher, dado que sin esto nos daría error.

composer require pusher/pusher-php-server

Ahora vamos a abrir nuestro archivo de configuración config/app.php y buscamos el apartado Application Service Providers, descomentamos la parte de BroadcastServiceProvider::class quedando así:

        /*
         * Application Service Providers...
         */
        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\RouteServiceProvider::class,

Nota: Si vamos a usar canales privado debemos configurarlo en BroadcastServiceProvider, podríamos dejarlo así.

Ahora vamos a abrir el archivo config/broadcasting.php, buscamos la parte de pusher y lo dejamos de esta forma

'pusher' => [
            'driver' => 'pusher',
            'key' => env('PUSHER_APP_KEY'),
            'secret' => env('PUSHER_APP_SECRET'),
            'app_id' => env('PUSHER_APP_ID'),
            'options' => [
                'cluster' => env('PUSHER_APP_CLUSTER'),
                'encrypted' => true,
                'useTLS' => env('PUSHER_SCHEME') === 'https',
                'host' => env('PUSHER_HOST', '127.0.0.1'),
                'port' => env('PUSHER_PORT', 6001),                
                'scheme' => env('PUSHER_SCHEME', 'http'),            
                'curl_options' => [
                    CURLOPT_SSL_VERIFYHOST => 0,
                    CURLOPT_SSL_VERIFYPEER => 0,
                ]
            ],
        ],

Ahora vamos a crear un evento para hacer nuestra prueba de envío hacia Soketi

php artisan make:event MessageSent

Nuestro archivo quedará así

<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class MessageSent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $message;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct($message)
    {
        $this->message = $message;
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return Channel|array
     */
    public function broadcastOn()
    {
        return new Channel('public');
    }
}

Hemos creado un canal llamado “public”, este evento recibirá un parámetro.

Ahora para probar que el evento al llega a soketi vamos a hacerlo directamente en nuestro archivo de rutas web.php, esto es solo para probar dependerá de la necesidad de cada uno, ya sea para un controlador, comando, job, etc.

Route::get('fire', function(){
    try {
        $data = ['time' => time()];
        App\Events\MessageSent::dispatch($data);
        return response()->json($data);
    } catch (\Throwable $th) {
        dd($th->getMessage());
    }
});

Aquí podemos ver en la imagen, lo que recibe Soketi y la respuesta de Laravel en el navegador.

Ahora lo que vamos a hacer es mostrar los mensajes que enviamos a Soketi en VueJs, para este ejemplo usaremos Laravel con VueJs.
Debemos crear otro proyecto Laravel (por ejemplo websockets.local), en nuestro proyecto instalaremos estos paquetes que necesitará VueJs

npm install --save-dev laravel-echo pusher-js

Vamos a resources/js/bootstrap.js y agregamos esto

import Echo from 'laravel-echo';
window.Pusher = require('pusher-js');

const token = "eyJ0eXAiOiJK"; // Esta línea declara una constante llamada 'token' y le asigna el valor "eyJ0eXAiOiJK".

window.Echo = new Echo({
    broadcaster: 'pusher', // Esta línea crea una nueva instancia de la clase Echo de Pusher.
    key: process.env.MIX_PUSHER_APP_KEY, // Esta línea establece la clave de la aplicación Pusher.
    wsHost: 'soketi.local', // Esta línea establece la dirección del host del servidor WebSocket.
    wsPort: 80, // Esta línea establece el puerto del servidor WebSocket.
    wssPort: null, // Esta línea establece el puerto del servidor WebSocket seguro.
    forceTLS: false, // Esta línea deshabilita el uso forzado de TLS.
    encrypted: false, // Esta línea deshabilita la conexión encriptada.
    disableStats: true, // Esta línea deshabilita las estadísticas de conexión.
    enabledTransports: ['ws'], // Esta línea establece el transporte de conexión a 'ws'.

    //Optional
    authEndpoint: 'http://laravel.local/broadcasting/auth', // Esta línea establece la URL del endpoint de autenticación.
    auth: {
        headers: {
            Authorization: "Bearer " + token, // Esta línea establece el encabezado de autorización con el token.
            Accept: "application/json", // Esta línea establece el encabezado de aceptación a 'application/json'.
        },
    }
});

Y en nuestro archivo .env

PUSHER_APP_KEY='Bg8Tm59X2Ea'
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"

Esta configuración en algo más complicada en caso necesitamos obtener los datos que requieran una autentificación.
Para nuestro caso podemos eliminar la parte de authEndpoint y auth que nos funcionará sobre nuestra canal público.

Ahora creamos un componente para VueJs esto lo podemos hacer dentro de la carpeta: resources/js/components/SoketiMessage.vue

<template>
    <div>
        <p> Mostrar mensaje desde soketi: {{ newMessage } </p>
    </div>
</template>

<script>
    export default{
        data() {
            return {
                newMessage: ''
            }
        },
        mounted() {
            window.Echo.channel('public')
            .listen('MessageSent', (e) => {
                this.newMessage=e.message
            })

            /*
            window.Echo.private('orders')
            .listen('DataInformation', (e) => {
                this.newMessage = e.message;
            });
            */
        }
    }
</script>

He agregado una parte de código comentado por si se necesita usar un canal privado, sería descomentar el código y reemplazar por el canal privado y el evento deseado.

No olviden la parte donde vamos a registrar nuestro componente de vue en el archivo resources/js/app.js

Vue.component('soketi-message', require('./components/SoketiMessage.vue').default);

En este ejemplo agregar el componente en el archivo welcome.blade.php para mostrar los datos que recibiremos.

<div class="flex justify-center mt-4">
    <soketi-message></soketi-message>
</div>

No olviden compilar todo

npm run dev

En este último paso lo que haremos es, disparar el evento desde laravel.local/fire y recibir los datos a través en websockets.local

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *