
Se preparó la traducción del artículo para los estudiantes del curso profesional "Framework Laravel"
Frek Van der Herten y el equipo de Spatie han trabajado duro durante mucho tiempo en el Laravel Event Projector, un paquete que le permite aplicar el concepto de Event Sourcing al marco de Laravel. ¡Y finalmente, la primera versión estable (v1.0.0) está disponible!
Puede instalar Event Projector en su proyecto utilizando Composer y, gracias a la detección automática de paquetes en Laravel, ¡ponerse a trabajar inmediatamente después de publicar las migraciones y la configuración de paquetes!
composer require spatie/laravel-event-projector:^1.0.0
Event Projector requiere PHP 7.2, por lo que su aplicación debe ser compatible con la última versión de PHP, aunque el marco Laravel necesita una versión PHP de al menos 7.1.3.
¿Qué es "generación de eventos"?
En el artículo Generando eventos, este concepto se describe de la siguiente manera:
En lugar de almacenar el estado actual de los datos en el dominio, use para registrar la secuencia completa de acciones realizadas en estos datos, el almacenamiento que opera en el modo de solo agregar solo agrega datos. El almacenamiento actúa como un sistema de registros y se puede utilizar para materializar objetos de dominio. Esto nos permite simplificar las tareas en áreas temáticas complejas, ya que no hay necesidad de sincronizar el modelo de datos y el área temática, lo que conduce a una escalabilidad mejorada, una mayor productividad y eficiencia operativa. Este enfoque garantiza la coherencia de los datos transaccionales, y también le permite mantener un registro completo de cambios e historial, lo que permite llevar a cabo acciones compensatorias.
Te recomiendo que leas el artículo completo. Proporciona una excelente descripción de esta plantilla, expresa consideraciones para un uso adecuado y describe situaciones en las que puede ser útil.
También me gusta la explicación del concepto de generación de eventos, que se da en la introducción a la documentación de Event Projector:
La generación de eventos es la misma con respecto a los datos que Git con respecto al código. La mayoría de las aplicaciones solo almacenan su estado actual en la base de datos. Se pierde una cantidad significativa de información útil: no sabe cómo la aplicación alcanzó este estado.
El concepto de generación de eventos es un intento de resolver este problema guardando todos los eventos que ocurren en su aplicación. El estado de la aplicación se forma como resultado de escuchar estos eventos.
Para facilitar la comprensión, considere un pequeño ejemplo de la vida. Imagina que eres un banco. Tus clientes tienen cuentas. Mantener solo información sobre el saldo de la cuenta no es suficiente. También debe recordar todas las transacciones. Al usar la plantilla de generación de eventos, el saldo de la cuenta no será solo un campo separado en la base de datos, sino un valor calculado en función de la información de la transacción almacenada. Este es solo uno de los muchos beneficios que ofrece el concepto de generación de eventos.
Este paquete está diseñado para familiarizar a los usuarios del marco Laravel con el concepto de generación de eventos y facilitar su uso en la práctica.
Parece que Event Projector ayuda a simplificar el trabajo con el patrón de generación de eventos. La documentación también me ayudó a descubrir cómo usar este enfoque como parte de los conceptos del marco de Laravel que ya conozco.
Conceptos básicos de eventos de Laravel
Para comprender cómo funciona la generación de eventos en el paquete Event Projector y qué componentes están involucrados en este proceso, debe leer la sección Creación del primer proyector .
En un nivel alto (perdóneme si no soy completamente correcto en mi evaluación, ya que la generación de eventos es un concepto nuevo para mí) la generación de eventos usando el Proyector de eventos incluye:
- Modelos elocuentes
- Eventos que implementan la interfaz ShouldBeStored
- Clases de proyectores
Un ejemplo de una clase de modelo con el método estático createWithAttributes
, proporcionado en la documentación:
namespace App; use App\Events\AccountCreated; use App\Events\AccountDeleted; use App\Events\MoneyAdded; use App\Events\MoneySubtracted; use Illuminate\Database\Eloquent\Model; use Ramsey\Uuid\Uuid; class Account extends Model { protected $guarded = []; protected $casts = [ 'broke_mail_send' => 'bool', ]; public static function createWithAttributes(array $attributes): Account { $attributes['uuid'] = (string) Uuid::uuid4(); event(new AccountCreated($attributes)); return static::uuid($attributes['uuid']); } public function addMoney(int $amount) { event(new MoneyAdded($this->uuid, $amount)); } public function subtractMoney(int $amount) { event(new MoneySubtracted($this->uuid, $amount)); } public function delete() { event(new AccountDeleted($this->uuid)); } public static function uuid(string $uuid): ?Account { return static::where('uuid', $uuid)->first(); } }
Aquí debe prestar atención a los eventos AccountCreated
, MoneyAdded
, MoneySubtracted
y AccountDeleted
, activados respectivamente para abrir una cuenta, agregar dinero a la cuenta, retirar dinero de la cuenta y eliminarla.
El siguiente es un ejemplo del evento MoneyAdded
(agregar dinero a una cuenta). La interfaz ShouldBeStored le dice al paquete del Proyector de eventos que este evento debe guardarse:
namespace App\Events; use Spatie\EventProjector\ShouldBeStored; class MoneyAdded implements ShouldBeStored { public $accountUuid; public $amount; public function __construct(string $accountUuid, int $amount) { $this->accountUuid = $accountUuid; $this->amount = $amount; } }
Y finalmente, un ejemplo parcial de un controlador de eventos dentro de la clase de proyector para reponer fondos en la cuenta (mi tipo favorito de evento bancario):
public function onMoneyAdded(MoneyAdded $event) { $account = Account::uuid($event->accountUuid); $account->balance += $event->amount; $account->save(); }
Para vincular todo esto, considere un ejemplo de la documentación sobre cómo crear una nueva cuenta y agregar fondos:
Account::createWithAttributes(['name' => 'Luke']); Account::createWithAttributes(['name' => 'Leia']); $account = Account::where(['name' => 'Luke'])->first(); $anotherAccount = Account::where(['name' => 'Leia'])->first(); $account->addMoney(1000); $anotherAccount->addMoney(500); $account->subtractMoney(50);
Sospecho que el saldo en las cuentas de Luke y Leia se expresa en préstamos estándar galácticos, aunque en general dudo que conduzcan abiertamente tales operaciones.
También me llamó la atención la siguiente ventaja de generar eventos usando este paquete, como se indica en la documentación:
Un punto interesante cuando se trabaja con proyectores: se pueden crear después de que ocurrieron los eventos. Imagine que el banco desea recibir un informe sobre el saldo promedio de cada cuenta. En este caso, será suficiente crear un nuevo proyector, reproducir todos los eventos y obtener estos datos al final.
La idea misma de crear nuevos proyectores al final de los eventos parece muy prometedora. Resulta que no tiene que obtener todos los datos "correctos" de antemano, pero puede llegar al resultado de forma iterativa.
En cuanto al rendimiento, según la documentación, el acceso a los proyectores "ocurre muy rápidamente".
¿Quieres saber más?
Para comenzar, le recomiendo que lea la documentación del Proyector de eventos y asegúrese de tener instalada la última versión de PHP 7.2. El equipo de Spatie también cargó una aplicación de muestra en Laravel , demostrando las capacidades del paquete Event Projector.
Puede descargar el código, marcar el repositorio con un asterisco y también contribuir al desarrollo del proyecto Event Projector en GitHub . Al momento de escribir este artículo, el proyecto Event Projector ya tiene 15 participantes, cuyos esfuerzos hicieron posible el lanzamiento estable de 1.0. ¡Buen trabajo, Spatie! Estoy seguro de que Event Projector será otro gran paquete que será apreciado por la comunidad de Laravel.