DEV Community

Marcelo Chiaretto
Marcelo Chiaretto

Posted on

1

DTOs e PHP: simplificando a transferência de dados entre as camadas da aplicação

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
    {
        //
    }
}


Enter fullscreen mode Exit fullscreen mode

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
    ) {}
}


Enter fullscreen mode Exit fullscreen mode

E na classe CreateProduct podemos alterar o método execute():



public function execute(ProductDto $data): Product
{
    //
}


Enter fullscreen mode Exit fullscreen mode

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:

Instanciando a classe ProductDto

E também na utilização desses dados:

Utilizando objeto ProductDto

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']
    );
}


Enter fullscreen mode Exit fullscreen mode

E utilizando dessa forma:



$data = ProductDto::fromRequest($request);


Enter fullscreen mode Exit fullscreen mode

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
    {
        //
    }
}


Enter fullscreen mode Exit fullscreen mode

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read more →

Top comments (0)

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up