Por qué el CRUD convencional deja de funcionar cuando el proyecto crece
\n\nImagine: está escribiendo una tienda online en PHP. Al principio todo es simple: agregó un producto, cambió el precio, lo eliminó. Pero pasan seis meses y aparecen nuevos requisitos: auditoría de todos los cambios, restauración de datos a una fecha determinada, lógica compleja de descuentos. El CRUD (Create, Read, Update, Delete) convencional comienza a desmoronarse. La base de datos se convierte en un caos, y cada nueva solicitud del cliente requiere reescribir la mitad del sistema.
\n\n¿Le suena familiar? Entonces definitivamente le serán útiles CQRS (Command Query Responsibility Segregation) y Event Sourcing: dos potentes patrones que cambian el enfoque del desarrollo. En este artículo los analizaremos con ejemplos reales en PHP, para que pueda aplicarlos en sus proyectos.
\n\nQué son CQRS y Event Sourcing en palabras sencillas
\n\nCQRS: separación de comandos y consultas
\n\nCQRS es un patrón arquitectónico que divide las operaciones en dos tipos: comandos (cambian el estado) y consultas (leen el estado). En el MVC clásico, tanto el controlador como el modelo trabajan con las mismas entidades. CQRS propone separar estas responsabilidades.
\n\nImagine una biblioteca: hay una mesa separada para registrar libros (comandos) y una mesa separada para leer (consultas). Nadie interfiere con nadie, y cada una está optimizada para su tarea.
\n\nEvent Sourcing: historial de cambios en lugar del estado actual
\n\nEvent Sourcing es una forma de almacenar datos donde no se guarda el estado actual de un objeto, sino la secuencia de todos los eventos que llevaron a ese estado. En lugar de una sola fila "Pedido Nº123: estado = entregado", usted almacena: "Pedido creado → Pagado → Enviado → Entregado".
\n\nEs como una grabación de video en lugar de una fotografía: siempre puede retroceder y ver qué sucedió en cualquier momento.
\n\nCuándo aplicar CQRS y Event Sourcing en PHP
\n\nEstos patrones no son una bala de plata. Para un blog simple son excesivos. Pero estos son los escenarios donde son indispensables:
\n\n- \n
- Lógica de dominio compleja (finanzas, reservas, logística) \n
- Requisitos de auditoría — necesita saber quién y cuándo modificó los datos \n
- Restauración del estado a cualquier fecha \n
- Arquitectura de microservicios — los eventos se transmiten fácilmente entre servicios \n
- Alta carga de lectura — se puede crear un modelo de lectura separado, optimizado para consultas \n
Si su proyecto es una tienda online con miles de pedidos, un sistema CRM o una aplicación bancaria — CQRS y Event Sourcing definitivamente le serán útiles.
\n\nImplementación práctica de CQRS en PHP
\n\nPasemos al código. Implementaremos un sistema simple de gestión de pedidos. Empecemos con CQRS.
\n\nPaso 1: Definir comandos y consultas
\n\nUn comando es un DTO (Data Transfer Object) que contiene todos los datos para ejecutar una operación. El comando nunca devuelve datos — solo cambia el estado.
\n\n<?php\n// src/Application/Command/CreateOrderCommand.php\nnamespace App\\Application\\Command;\n\nclass CreateOrderCommand\n{\n public function __construct(\n public readonly string $orderId,\n public readonly string $customerId,\n public readonly array $items, // [['productId' => '...', 'quantity' => 2], ...]\n public readonly \\DateTimeImmutable $createdAt\n ) {}\n}\n\n\nUna consulta también es un DTO, pero para lectura. Puede contener filtros y devolver datos.
\n\n<?php\n// src/Application/Query/GetOrderQuery.php\nnamespace App\\Application\\Query;\n\nclass GetOrderQuery\n{\n public function __construct(\n public readonly string $orderId\n ) {}\n}\n\n\nPaso 2: Crear manejadores de comandos
\n\nUn manejador de comandos es un servicio que ejecuta la lógica de negocio. Recibe un comando y cambia el estado