Este é meu primeiro artigo, então prepare-se para pegar as pedras.
Ao escrever um novo método ou serviço, tentamos abstraí-lo tanto quanto possível das dependências externas para que a nova funcionalidade implemente apenas a lógica estabelecida para ele. Na verdade, isso é o que nos diz um dos princípios SOLID - o princípio da responsabilidade única .
Constantemente encontro um código onde se um método tem mais de dois argumentos de entrada, um condicional (array $ args) é adicionado, o que implica a implementação de uma verificação para a presença de uma chave, ou se está ausente, e então a probabilidade que o método pode ser pintado em tempo de execução aumenta
Talvez, tal abordagem em PHP tenha se desenvolvido historicamente, devido à falta de tipagem forte e OOP. Afinal, para mim, somente a partir da versão 7 foi possível implementar mais ou menos a digitação + OOP, usando strict_types e type hinting.
Além disso, a chamada de tais métodos pode ser acompanhada por uma descrição do array que passaremos. Ou algum tipo de array com lixo é passado e o método simplesmente pega as chaves de que precisa. Por exemplo, um serviço para criar um usuário:
$userService->create([
'name' => $object->name,
'phone' => $object->phone,
'email' => $object->email,
]);
, DTO’. DTO , , . . , , , .
DTO, , . . , , , , .
ClassTransformer
. . , . Laravel :
class UserController extends Controller {
public function __construct(
private UserService $userService,
) {}
public function createUser(CreateUserRequest $request)
{
$dto = ClassTransformer::transform(CreateUserDTO::class, $request);
$user = $this->userService->create($dto);
return response(UserResources::make($user));
}
}
class CreateUserDTO
{
public string $name;
public string $email;
public string $phone;
}
: name, phone email. , , , . . transform , object, .
. , DTO, :
class CreateUserDTO
{
public string $name;
public string $email;
public string $phone;
public static function transform(mixed $args):CreateUserDTO
{
$dto = new self();
$dto->name = $args['fullName'];
$dto->email = $args['mail'];
$dto->phone = $args['phone'];
return $dto;
}
}
, , . ? , PHPDoc . , :
class PurchaseDTO
{
/** @var array<\DTO\ProductDTO> $products Product list */
public array $products;
/** @var \DTO\UserDTO $user */
public UserDTO $user;
}
, . .
, .. . alias , .
?
,
,
IDE .
, . Spatie - https://github.com/spatie/data-transfer-object
DTO, DTO, , . , new DTO() .
, , NestJS - plainToClass. , , . ORM ( ), :)
Roadmap
Implemente o método afterTransform que será chamado depois que o DTO for inicializado. Isso permitirá que você personalize o elenco de forma mais flexível para a classe. No momento, se as chaves de entrada forem diferentes dos DTOs internos, você mesmo precisa descrever o método de transformação. E se dos 20 parâmetros apenas um tiver uma chave diferente, teremos que descrever a conversão de todos os 20. E com o método afterTransform, podemos personalizar a conversão apenas do parâmetro de que precisamos, e todo o resto será processado por o pacote.
Suporte a atributos PHP 8
Isso é tudo.