Laravel Reverb: la nueva solución para la comunicación en tiempo real

- Andrés Cruz

Laravel Reverb es un nuevo miembro de la familia Laravel, que fue lanzado hace apenas una semana. Es un nuevo servidor WebSocket propio para las aplicaciones Laravel, que ofrece soluciones completas para la comunicación en tiempo real entre el cliente y el servidor.

¿Te preguntas qué hace que Laravel Reverb sea especial? Este artículo desglosará sus características interesantes y le mostrará un ejemplo de la vida real de cómo usarlo en un proyecto Laravel real.

Laravel Reverb: explorando las características clave

Con Laravel Reverb, ahora puedes lograr más con tus proyectos basados en Laravel gracias a un nuevo conjunto de características y capacidades. Como se mencionó anteriormente, el objetivo principal de Reverb es garantizar una comunicación fluida entre el cliente y el servidor de la aplicación web a través de la interacción en tiempo real. Aquí hay un resumen rápido de lo que Laravel Reverb puede hacer por usted:

  1. Transmisión de eventos: Reverb simplifica la transmisión de datos en tiempo real, lo que permite a las aplicaciones actualizar fácilmente la interfaz de usuario sin necesidad de recargar la página.
  2. Integración de WebSockets: Reverb ofrece un método eficaz para crear canales de comunicación bidireccionales en tiempo real entre clientes y servidores mediante el uso de WebSockets.
  3. API elegante: ofrece una API fantástica y expresiva que sigue la filosofía de Laravel y facilita a los desarrolladores la creación de funciones sofisticadas en tiempo real con poco o ningún código.
  4. Integración frontal perfecta: Reverb ha sido diseñado para integrarse sin esfuerzo con marcos frontend conocidos. Facilita a los desarrolladores agregar datos en tiempo real a sus aplicaciones Laravel sin tener que realizar cambios significativos.
  5. Velocidad: dado que Reverb está diseñado para una comunicación rápida, gestiona de manera eficiente miles de conexiones para garantizar una capacidad de respuesta en tiempo real.
  6. Escalabilidad: está diseñado para escalarse fácilmente, utilizando Redis para la distribución efectiva de conexiones y datos entre múltiples servidores.

Laravel Reverb: ¿Cuáles son los casos de uso del mundo real?

  1. Debido a su adaptabilidad, Laravel Reverb puede manejar una amplia gama de tareas, desde pequeños proyectos hasta grandes sistemas de nivel empresarial. A continuación se muestran algunos casos de uso prácticos:
  2. Plataformas de comercio electrónico: para actualizaciones de productos en vivo, gestión de inventario y notificaciones instantáneas sobre pedidos de clientes y estado de envío.
  3. Sitios de redes sociales: implementación de feeds, notificaciones y sistemas de chat en tiempo real, mejorando la participación y la interactividad del usuario.
  4. Herramientas de colaboración en línea: creación de plataformas donde varios usuarios pueden trabajar en documentos o proyectos simultáneamente, con cambios reflejados en tiempo real.
  5. Actualizaciones de deportes en vivo y servicios de transmisión: brindan a los usuarios actualizaciones instantáneas sobre resultados, eventos o contenido de transmisión sin latencia.

Implementación de Laravel Reverb en un proyecto de chat

Para obtener más información sobre Laravel Reverb, creemos un proyecto de minichat. El proyecto incluirá una lista de salas de chat y los usuarios podrán unirse a cualquiera de las salas y luego comenzar a chatear entre ellos.

Paso 1: configurar el proyecto Laravel

Primero, asegúrese de tener Composer instalado en su sistema. Luego, cree un nuevo proyecto Laravel ejecutando lo siguiente:

composer create-project --prefer-dist laravel/laravel laravel-reverb-chat

Paso 2: Instalar Laravel Reverb

Instale Laravel Reverb ejecutando el siguiente comando:

php artisan install:broadcasting
npm install --save laravel-echo pusher-js

Una vez que hayas instalado Reverb, ahora puedes modificar su configuración desde el archivo `config/reverb.php`. Para establecer una conexión con Reverb, se debe intercambiar un conjunto de credenciales de “aplicación” de Reverb entre el cliente y el servidor. Estas credenciales se configuran en el servidor y se utilizan para verificar la solicitud del cliente. Puede definir estas credenciales utilizando las siguientes variables de entorno:

BROADCAST_DRIVER=reverb
REVERB_APP_ID=my-app-id
REVERB_APP_KEY=my-app-key
REVERB_APP_SECRET=my-app-secret

Paso 3: ejecutar el servidor

Puedes iniciar el servidor Reverb usando el comando reverb:start Artisan:

php artisan reverb:start

De forma predeterminada, el servidor Reverb se iniciará en 0.0.0.0:8080, lo que lo hace accesible desde todas las interfaces de red.

Si desea configurar un host o puerto específico, puede usar las opciones –host y –port al iniciar el servidor.

php artisan reverb:start --host=127.0.0.1 --port=9000

También puede definir las variables de entorno REVERB_SERVER_HOST y REVERB_SERVER_PORT en el archivo de configuración .env de su aplicación.

Paso 4: configurar la base de datos

Abra su archivo .env y ajuste la configuración para configurar su base de datos. A continuación se muestra un ejemplo que utiliza SQLite para simplificar:

DB_CONNECTION=sqlite
DB_DATABASE=/path/to/database.sqlite

Puedes crear una base de datos SQLite simplemente ejecutando:

touch /path/to/database.sqlite

Para esta demostración, crearemos cinco salas predefinidas. Comencemos generando una migración para una tabla de habitaciones.

php artisan make:model Room --migration

Para hacerlo más simple, solo se crea atributos de nombre para este modelo.

Schema::create('rooms', function (Blueprint $table) {
   $table->id();
   $table->string('name');
   $table->timestamps();
});

Después de eso, siembre la base de datos con cinco salas. Crea un seeder:

php artisan make:seeder RoomsTableSeeder 

DB::table('rooms')->insert([
   ['name' => 'Room 1'],
   ['name' => 'Room 2'],
   ['name' => 'Room 3'],
   ['name' => 'Room 4'],
   ['name' => 'Room 5'],
]);

Ejecutar el seeder:

php artisan db:seed --class=RoomsTableSeeder

Paso 5: crear evento

Dentro del directorio `app/Events`, crea un nuevo archivo MessageSent.php. Este archivo es responsable de transmitir nuevos mensajes a salas de chat dedicadas. Aquí tienes un ejemplo básico:

class MessageSent implements ShouldBroadcast
{
   use Dispatchable, InteractsWithSockets, SerializesModels;
   public $userName;
   public $roomId;
   public $message;
   public function __construct($userName, $roomId, $message)
   {
       $this->userName = $userName;
       $this->roomId = $roomId;
       $this->message = $message;
   }
   public function broadcastOn() : Channel
   {
       return new Channel('chat.' . $this->roomId);
   }
   public function broadcastWith()
   {
       return [
           'userName' => $this->userName,
           'message' => $this->message,
       ];
   }

Paso 6: Crear páginas

En este proyecto, tendremos dos páginas: una para mostrar una lista de salas y otra para salas de chat individuales. Comenzaremos creando plantillas Blade para mostrar las habitaciones. Llamemos a estas vistas index.blade.php y chat.blade.php y guárdelas en un directorio de salas en recursos/vistas. A continuación, crearemos un controlador y una ruta para navegar a estas páginas.

index.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Chat Rooms</title>
</head>
<body>
<div id="app">
   <h1>Chat Rooms</h1>
   <ul>
       @foreach($rooms as $room)
           <li>
               <a href="{{ route('rooms.show', $room->id) }}">Join {{ $room->name }}</a>
           </li>
       @endforeach
   </ul>
</div>
</body>
</html>

chat.blade.php

Configure un formulario básico para mostrar chats y un campo de entrada simple para mensajes. Asegúrese de haber importado Echo y Pusher en el archivo app.js.

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Chat Room: {{ $room->name }}</title>
   @vite(['resources/css/app.css'])
   @vite(['resources/js/app.js'])
</head>
<body>
<div id="app">
   <h2>Chat Room: {{ $room->name }}</h2>
   <div id="messages"
        style="border: 1px solid #ccc; margin-bottom: 10px; padding: 10px; height: 300px; overflow-y: scroll;">
       <!-- Messages will be displayed here -->
   </div>
   <input type="text" id="messageInput" placeholder="Type your message here..." autofocus>
   <button onclick="sendMessage()">Send</button>
</div>
<script>
   document.addEventListener('DOMContentLoaded', function () {
       const roomId = "{{ $room->id }}";
       Echo.channel(`chat.${roomId}`)
           .listen('MessageSent', (e) => {
               const messages = document.getElementById('messages');
               const messageElement = document.createElement('div');
               messageElement.innerHTML = `<strong>${e.userName}:</strong> ${e.message}`;
               messages.appendChild(messageElement);
               messages.scrollTop = messages.scrollHeight; // Scroll to the bottom
           });
   })
   function sendMessage() {
       const messageInput = document.getElementById('messageInput');
       const message = messageInput.value;
       messageInput.value = ''; // Clear input
       const roomId = "{{$room->id}}"
       fetch(`/rooms/${roomId}/message`, {
           method: 'POST',
           headers: {
               'X-CSRF-TOKEN': '{{ csrf_token() }}',
               'Content-Type': 'application/json'
           },
           body: JSON.stringify({message: message})
       }).catch(error => console.error('Error:', error));
   }
</script>
</body>
</html>

Ejecutamos:

php artisan make:controller RoomsController

Importamos Echo y Pusher:

import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
   broadcaster: 'reverb',
   key: import.meta.env.VITE_REVERB_APP_KEY,
   wsHost: import.meta.env.VITE_REVERB_HOST,
   wsPort: import.meta.env.VITE_REVERB_PORT ?? 80,
   wssPort: import.meta.env.VITE_REVERB_PORT ?? 443,
   forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
   enabledTransports: ['ws', 'wss'],
});

Ahora, configuremos los métodos de visualización:

class RoomsController extends Controller
{
   public function index()
   {
       $rooms = Room::all();
       return view('rooms.index',[
           'rooms' => $rooms
       ]);
   }
   public function show(Room $room)
   {
       return view('rooms.chat', [
           'roomId' => $room->id,
           'messages' => []
       ]);
   }
}

Para simplificar las cosas, creemos un punto final postMessage y agréguelo al web.php.

php artisan make:controller ChatController
class ChatController extends Controller
{
   public function postMessage(Request $request, $roomId)
   {
       $userName = 'User_' . Str::random(4);
       $messageContent = $request->input('message');
       MessageSent::dispatch($userName, $roomId, $messageContent);
       return response()->json(['status' => 'Message sent successfully.']);
   }
}

Paso 7: Ejecutar proyecto

Para ejecutar el proyecto Laravel, necesitamos ejecutar el siguiente comando:

php artisan serve

Para el frente inicial:

npm run dev

Cola de inicio:

php artisan queue:listen

Ejecutar reverb:

php artisan reverb:start

 

 

Artículo original

https://redberry.international/laravel-reverb-real-time-communication/

Andrés Cruz

Desarrollo con Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter

Andrés Cruz en Udemy

Acepto recibir anuncios de interes sobre este Blog.