Skip to content

⚠️ Aunque este paquete funciona, es mejor usar este otro ⚠️

Dtos a partir de Requests

Clase auxiliar que ayuda a mapear FormRequest de Laravel a un Dto.

¿Qué es un DTO?

Un DTO (objeto de transferencia de datos) es un objeto muy simple que solo contiene datos. Aprovechando las propiedades readonly de las nuevas versiones de PHP y las mejoras en el sistema de tipos, podemos crear objetos muy ligeros que están totalmente tipados y además son inmutables, lo que puede facilitar el desarrollo de otras capas de la aplicación. En otras palabras, hacen que los datos que devuelven sean más predecibles y fiables que en un array normal.

Uso

El objetivo principal de este paquete es separar la infraestructura (Request) de la capa de aplicación, de una forma fácil y que no suponga forzar una estructura determinada en toda la aplicación, sino de forma opcional en los casos que cada uno quiera. Hay que definir 2 cosas:

  • por un lado, un request normal de Laravel, con las reglas de validación habituales (CreateTagRequest en el ejemplo)
  • por otro lado, la clase del Dto, que debe implementar \Bittacora\Support\Dtos\Dto

La interfaz Bittacora\Support\Dtos\Dto solo define el siguiente método:

public static function map(array $data): self;

Los DTOs que la implementen recibirán en $data los datos validados del Request de Laravel que queramos usar para construirlos. En ese método, cada DTO debe mapear los elementos del array del Request a sus propiedades, por ejemplo:

final class CreateTagDto implements Dto
{

    public function __construct(
        public readonly string $name        
    ) {
        // ...
    }    

    public static function map(array $data): self
    {
        return new self($data['name']);
    }
}

Nota: Uso un método estático (map) para "obligar" a llamar al constructor. De esta forma los DTOs construidos llamando directamente al constructor y los que se construyan llamando a map serán instanciados de la misma forma. Esto es útil para saltarse el mapeo en los tests, por ejemplo.

Después, en el controlador, construimos el DTO de la siguiente forma:

public function store(CreateTagRequest $request): void
{
    $dto = (new RequestDtoBuilder($request, CreateTagDto::class))->toDto();
    // ... 
}

A partir de aquí, en DTO tenemos un objeto con propiedades tipadas y de solo lectura que puede usarse donde queramos. Aparte de las ventajas que he puesto más arriba hay otras, como que el IDE sabrá exactamente qué propiedades hay disponibles y su tipo. También viene bien para el análisis estático con PHPStan o PSalm.