⚠️ 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 (
CreateTagRequesten 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.