Especialização em Backend com PHP & Laravel • Laravel 11 & PHP 8.3+ • Eloquent ORM, Sanctum, Filas, Horizon e APIs Corporativas


🗺️ Mapa Conceitual do Tópico

flowchart TD
    A["Cliente HTTP / Frontend"] --> B["API Gateway / Router"]
    B --> C["Controller / Handler"]
    C --> D["Service Layer (Regras de Negócio)"]
    D --> E["Repository / ORM (Persistência)"]
    E --> F["Banco de Dados / Cache"]

    subgraph ARQ["Arquitetura do Capítulo"]
        G["Conceito: Eloquent API Resources e Serialização de Dados REST"]
        H["Segurança, Validação e Resiliência"]
        I["Alta Performance e Escalabilidade"]
    end

    D --> ARQ

    style A fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px
    style B fill:#fff3e0,stroke:#ff9800,stroke-width:2px
    style C fill:#ede7f6,stroke:#7e57c2,stroke-width:2px
    style D fill:#e8f5e9,stroke:#4caf50,stroke-width:2px
    style E fill:#fce4ec,stroke:#e91e63,stroke-width:2px
    style F fill:#f3e5f5,stroke:#9c27b0,stroke-width:2px

🏛️ 1. O Problema: Vazar o Model Direto na Resposta

Devolver um model Eloquent direto num return $produto; funciona porque o Laravel serializa via toArray()/toJson() — mas isso vaza toda coluna da tabela (incluindo password, timestamps internos, chaves estrangeiras cruas) e acopla o contrato da API à estrutura exata do banco: renomear uma coluna quebra todo cliente da API. API Resources resolvem isso com uma camada explícita de tradução entre o model e o JSON público.

<?php
// app/Http/Resources/ProdutoResource.php
namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class ProdutoResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'nome' => $this->nome,
            'preco_formatado' => 'R$ ' . number_format($this->preco, 2, ',', '.'),
            'criado_em' => $this->created_at->toISOString(),
            // sku, custo_interno, deleted_at etc. NUNCA aparecem -- so o que for listado aqui
        ];
    }
}

No controller: return new ProdutoResource($produto); para um único item, ou ProdutoResource::collection($produtos) para uma lista — o resource sabe se adaptar a ambos os casos.

🗂️ 2. ResourceCollection e o Envelope data

Quando o resultado é uma coleção paginada, ProdutoResource::collection() já envolve automaticamente a resposta num envelope {"data": [...]}. Para customizar esse envelope (adicionar metadados como total de registros, links de paginação, ou um bloco meta próprio), usa-se uma ResourceCollection dedicada:

<?php
// app/Http/Resources/ProdutoCollection.php
namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class ProdutoCollection extends ResourceCollection
{
    public function toArray($request): array
    {
        return [
            'data' => $this->collection,
            'meta' => [
                'total' => $this->collection->count(),
                'gerado_em' => now()->toISOString(),
            ],
        ];
    }
}

🔀 3. Campos Condicionais: whenLoaded, when e mergeWhen

Um erro comum é acessar uma relação ($this->categoria->nome) que não foi carregada via with() — isso dispara uma query N+1 silenciosa por trás do resource. whenLoaded() só inclui o campo se a relação já veio carregada, sem forçar uma nova consulta:

public function toArray(Request $request): array
{
    return [
        'id' => $this->id,
        'nome' => $this->nome,
        'categoria' => new CategoriaResource($this->whenLoaded('categoria')),
        // só aparece no JSON se o usuário autenticado for admin:
        'custo_interno' => $this->when($request->user()?->is_admin, $this->custo_interno),
    ];
}

Isso torna o Resource também uma camada de autorização de campo: a mesma entidade pode expor mais ou menos dados dependendo de quem está pedindo, sem duplicar a classe.



🔗 Recursos Pedagógicos do Capítulo 11

Recurso Didático Finalidade Link de Acesso
📊 Slides de Aula Apresentação visual interativa com Dark Mode e suporte a teclado Ver Slides
🧠 Quiz Formativo Teste interativo de fixação com feedback imediato por alternativa Fazer Quiz
💻 Exemplos de Código Demonstrações funcionais com código executável Ver Exemplos
🧩 Exercícios em 4 Níveis Lista progressiva de fixação com gabarito em bloco colapsável Resolver Exercícios

⬅️ Capítulo Anterior 📚 Sumário de Tópicos Próximo Capítulo ➡️