-
Notifications
You must be signed in to change notification settings - Fork 0
WebSockets Integration
BOUNDLY es un framework agnóstico diseñado bajo los principios de DDD (Domain-Driven Design). Esto significa que el Dominio (reglas de negocio) jamás debe saber qué herramienta de infraestructura estás utilizando para emitir eventos en tiempo real.
Hemos construido un "Puente de Broadcasting" interno. Esta guía te enseñará cómo enviar eventos WebSockets al cliente de forma limpia y arquitectónicamente perfecta.
Por defecto, BOUNDLY provee dos herramientas en su arquitectura que actúan como puente:
- Una Interfaz pura en tu Capa de Dominio:
Domain\Shared\Events\ShouldBroadcastToExterior - Un traductor técnico en la Capa de Infraestructura:
Infrastructure\Providers\BroadcastServiceProvider(junto con su adaptadorBroadcastableDomainEvent).
Tus entidades y eventos vivirán completamente libres de dependencias de Laravel (como Pusher o Reverb). Si mañana migras el sistema a Soketi, tu Dominio no sufrirá ni un solo cambio.
Como programador, tú decides si usar Laravel Reverb, Pusher, o Redis. Asumiremos que usarás Reverb (la opción recomendada actual).
-
Ingresa a la carpeta del proyecto y usa Composer para instalar Reverb (o la librería que prefieras).
composer require laravel/reverb php artisan install:broadcasting
-
Configura los accesos en tu archivo
.env.# Activa Reverb como motor por defecto (o pusher, log, redis) BROADCAST_CONNECTION=reverb # Configuración de Reverb (Te la proveerá el comando de instalación) REVERB_APP_ID=991986 REVERB_APP_KEY=ehx5egdh5bbenrgeknpf REVERB_APP_SECRET=7aboiain4jpj6j3ojflb REVERB_HOST="localhost" REVERB_PORT=8080 REVERB_SCHEME=http VITE_REVERB_APP_KEY="${REVERB_APP_KEY}" VITE_REVERB_HOST="${REVERB_HOST}" VITE_REVERB_PORT="${REVERB_PORT}" VITE_REVERB_SCHEME="${REVERB_SCHEME}"
NOTA: Para emitir eventos encolados en segundo plano para alto rendimiento, asegúrate de tener QUEUE_CONNECTION=database y tu worker corriendo (php artisan queue:work), de lo contrario usa QUEUE_CONNECTION=sync para despacho inmediato.
Dentro del contexto donde haya ocurrido un cambio (ej. Domain/Posts/Events/), crea una clase PHP pura. Para conectarla al exterior, implementa la interfaz ShouldBroadcastToExterior.
<?php
namespace Domain\Posts\Events;
use Domain\Shared\Events\DomainEvent;
use Domain\Shared\Events\ShouldBroadcastToExterior;
class PostCreated extends DomainEvent implements ShouldBroadcastToExterior
{
public function __construct(
public int $postId,
public string $postTitle
) {
parent::__construct();
}
/**
* Canal donde el Frontend escuchará este evento.
*/
public function getBroadcastChannel(): string
{
// Se emitirá en el canal público "domain.posts.[id]"
return 'domain.posts.' . $this->postId;
}
/**
* Datos que se enviarán al Cliente vía Websockets
*/
public function getBroadcastData(): array
{
return [
'id' => $this->postId,
'title' => $this->postTitle,
'message' => '¡Un nuevo post ha surgido en el dominio!'
];
}
}En la Capa de Aplicación (Application\), invoca o despacha este evento cuando el Use Case lo merezca. El motor global de BOUNDLY (event()) lo capturará:
<?php
namespace Application\Posts\Actions;
use Infrastructure\FrameworkCore\Attributes\Action;
use Illuminate\Http\Request;
use Domain\Posts\Events\PostCreated;
#[Action(resource: 'posts/test', method: 'POST')]
class ExampleBroadcastAction
{
public function execute(Request $request)
{
// 1. Lógica del negocio (ej. guardar un Post)
$id = rand(1, 999);
$title = $request->input('title');
// 2. Disparar el evento de dominio (BOUNDLY orquesta hacia WebSockets)
event(new PostCreated($id, $title));
return [
'message' => 'Ejecutado e impulsado hacia ecosistema en tiempo real.'
];
}
}Todos tus eventos serán retransmitidos bajo el nombre universal DomainUpdate en la infraestructura subyacente de BOUNDLY, sin revelar la clase interna.
Ejemplo en tu Cliente con Laravel Echo:
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,
forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https',
enabledTransports: ['ws', 'wss'],
});
// Escuchar el canal definido por la Entidad (ej: domain.posts.45)
window.Echo.channel('domain.posts.45')
.listen('.DomainUpdate', (data) => {
console.log('¡Actualización desde el Dominio BOUNDLY!', data);
});(Es importante el punto .DomainUpdate al inicio del string en Laravel Echo, o registrar el namespace completo \DomainUpdate).
-
TuActionlanza un Evento Puro => - El Dispatcher de BOUNDLY ve la etiqueta
ShouldBroadcastToExterior=> - El Proveedor lo envuelve en un DTO Serializable Técnico =>
- Tu Motor (
Reverb/Pusher) recibe la petición => - Tu Cliente JavaScript/Mobile recibe la notificación
DomainUpdate.