Pular para conteúdo

Aula 17 - Laravel 10+ com Arquitetura de Serviços e DTOs 🐘

Objetivo Pedagógico

Objetivo: Arquitetura corporativa em Laravel moderna: desacoplamento de controladores com Service Layers, Data Transfer Objects tipados com readonly e Form Requests.


📑 1. Fundamentos Teóricos & Análise Técnica

O PHP moderno (versões 8.2 e 8.3+) transformou-se em uma linguagem fortemente tipada, expressiva e performática. No framework Laravel, a prática clássica de concentrar regras de negócio diretamente em Controllers densos (Fat Controllers) viola o princípio da responsabilidade única e impede a reutilização de lógica em comandos de console, jobs ou testes automatizados.

A arquitetura profissional em Laravel estrutura-se em: 1. Form Requests: Classes dedicadas (FormRequest) responsáveis por validar a entrada HTTP e autorizar a ação antes que o controlador seja acionado. 2. Data Transfer Objects (DTOs): Objetos imutáveis construídos com propriedades tipadas public readonly e promoção de propriedades no construtor (Constructor Property Promotion), garantindo dados sanitizados e estruturados. 3. Camada de Serviços (Service Layer): Classes puras que orquestram regras de negócio, transações de banco de dados e comunicação com serviços externos.

📐 Arquitetura Conceitual & Diagrama de Fluxo

graph TD
    HTTP["Requisição: POST /api/orders"] --> FormRequest["CreateOrderRequest (Validação)"]
    FormRequest --> Controller["OrderController (Camada Fina)"]
    Controller --> DTO["OrderDTO (Imutável Readonly)"]
    Controller --> Service["OrderService (Regras de Domínio)"]
    Service --> DB["Eloquent ORM / Database"]
    Service --> Event["Evento de Domínio Disparado"]
    style HTTP fill:#e1f5fe,stroke:#01579b
    style FormRequest fill:#fff3e0,stroke:#e65100
    style Service fill:#e8f5e9,stroke:#2e7d32

🔍 Pilares e Diretrizes Técnicas

Nesta unidade, aprofundamos os seguintes conceitos fundamentais: - Imutabilidade com readonly: Garantia de que os dados do DTO não sofram mutações acidentais após a criação. - Controllers Enxutos: Controladores com menos de 20 linhas que apenas convertem requisições em DTOs e retornam respostas. - Injeção Automática de Dependências: O Service Container do Laravel resolve serviços e dependências automaticamente. - Transações Declarativas: Uso de DB::transaction(fn() => ...) para consistência relacional.


🛠️ 2. Implementação Prática em PHP 8.2+, Laravel 10+ e Clean Architecture

Abaixo está a implementação técnica de referência, estruturada com padrões de engenharia de software e foco em robustez:

// OrderService.php (Service Layer com DTO Imutável em PHP 8.2)
<?php

namespace App\Services;

use App\Models\Order;
use Illuminate\Support\Facades\DB;

// DTO Imutável com Constructor Promotion
readonly class CreateOrderDTO {
    public function __construct(
        public int $userId,
        public float $totalAmount,
        public array $items
    ) {}

    public static function fromRequest(array $data): self {
        return new self(
            userId: (int) $data['user_id'],
            totalAmount: (float) $data['total_amount'],
            items: $data['items']
        );
    }
}

class OrderService {
    public function createOrder(CreateOrderDTO $dto): Order {
        return DB::transaction(function () use ($dto) {
            $order = Order::create([
                'user_id' => $dto->userId,
                'total_amount' => $dto->totalAmount,
                'status' => 'PENDING'
            ]);

            foreach ($dto->items as $item) {
                $order->items()->create([
                    'product_id' => $item['product_id'],
                    'quantity' => $item['quantity'],
                    'unit_price' => $item['unit_price']
                ]);
            }

            return $order->load('items');
        });
    }
}

💡 Análise Passo a Passo do Código

  1. Classe readonly Nativa: Todas as propriedades do DTO tornam-se imutáveis e fortemente tipadas sem boilerplate de getters/setters.
  2. Método Fábrica fromRequest: Encapsula a lógica de conversão do payload de entrada para o objeto tipado.
  3. Transação com DB::transaction: Garante que o pedido e seus respectivos itens sejam gravados com integridade atômica.

🎯 3. Próximos Passos & Sequência Didática