Ejemplo completo de DDD o Clean Architecture en PHP

Lamento si alguien viene buscando la solución. Es lo que estoy buscando yo.

Validación del request (el POST)

En los ejemplos de MVC sin frontend JS las validaciones se las dejan al framework. No vi casos complejos de donde meten las validaciones y en casos donde usan Command Handlers dejan las validaciones para despues, es decir, copian todos los datos inválidos al DTO para después, y en los casos MVC la validación es lo primero.

El Command del Command Handler.

En todos los ejemplos el command solo tiene 2 datos, que son obligatorios y se inicializa por constructor. Ningun ejemplo de un POST con un array de más de 3 datos.

En el caso de la WMDE (Wikimedia Alemania), tienen una función encargada de construir el command (aunque ellos usan UseCases) sin validación y con una simple copia.

El foro Flarum usa el patrón Command Bus pero el constructor generalmente tiene el $userId y un array $data que no tiene nada de tipado. Muy distinto de los ejemplos que nos los explican y nos tratan de convencer

Validaciones.

Validar el command es algo en lo que casi todos coinciden, pero nadie agrega un caso de un ítem relacionado que exista en la base de datos y que requiera validar, quizá ningún ejemplo sea valido, pero quizá crear un producto que esté relacionado a una tienda (el usuario que envía el post debe poder tener más de una tienda). Entonces ¿como se valida que el store_id pertenezca al usuario? ¿En que lugar se hace esa validación?

Mi idea es por un lado validar el request (en algún lugar) para devolver todos los errores juntos, y cuando se intenta crear el objeto, cargando los datos relacionados, lanzar excepciones de dominio, aquí si de a una.

Creación del objeto a guardar.

Nos llega el request como array pero no vamos a guardar eso así porque usamos Doctrine, entonces hacemos el new del objeto y empezamos a setear y a cargar los objetos relacionados (de nuevo porque ya los habíamos cargado para verificar si existían y realizar otras validaciones).

¿Como crear ese objeto? ¿Una factory con un método estático?

$product = ProductFactory::createFromRequest(ProductCreateRequest $request)

El $request es el DTO tipado, no el request del PSR-7.