O padrão DTO
O DTO (Data Transfer Object) é um padrão de projeto que visa ter objetos usados exclusivamente para a transferência de dados entre camadas de uma aplicação. É um objeto anêmico, ou seja, a classe tem apenas atributos e sem métodos que manipulem dados, apenas de construção do objeto.
Porque não um utilizar um array para receber dados em método?
Observe a classe CreateProduct
:
<?php
namespace App\Actions\Product;
use App\Product\Contracts\ProductRepository;
class CreateProduct
{
public function __construct(private ProductRepository $repository) {}
public function execute(array $data): Product
{
//
}
}
Como o método execute()
recebe um array associativo, quem instanciar essa classe precisará abrir o método e ver quais chaves do array será necessário informar.
Substituindo o array pelo DTO
Podemos construir uma classe DTO no PHP utilizando o modificador readonly
para que os atributos dos objetos não sejam alterados.
PHP 8.1:
<?php
namespace App\Dto;
readonly class ProductDto
{
public function __construct(
public string $name,
public string $description,
public float $price,
public int $quantity,
public int $categoryId,
public int $brandId,
public string $sku,
public string $ean
) {}
}
E na classe CreateProduct
podemos alterar o método execute()
:
public function execute(ProductDto $data): Product
{
//
}
Benefícios para a IDE
Ao utilizar a classe DTO no lugar do array associativo a IDE irá ajudar a identificar os atributos necessários:
E também na utilização desses dados:
Indo além com métodos estáticos
Para facilitar a criação desses objetos podemos criar métodos estáticos:
public static function fromRequest(Request $request): self
{
return new self(
name: $request->name,
description: $request->description,
price: $request->price,
quantity: $request->quantity,
categoryId: $request->category_id,
brandId: $request->brand_id,
sku: $request->sku,
ean: $request->ean
);
}
public static function fromArray(array $data): self
{
return new self(
name: $data['name'],
description: $data['description'],
price: $data['price'],
quantity: $data['quantity'],
categoryId: $data['categoryId'],
brandId: $data['brandId'],
sku: $data['sku'],
ean: $data['ean']
);
}
E utilizando dessa forma:
$data = ProductDto::fromRequest($request);
Quando não utilizar
Não vejo a necessidade de utilizar um DTO como parâmetro em métodos públicos que já indicam o dado que espera receber, como por exemplo um método que buscará uma lista de produtos pelos IDs informados:
class FindProducts
{
public function execute(array $productsIds): Product
{
//
}
}
Top comments (0)