API Platform Symfony REST: Tutorial Completo e Perguntas de Entrevista 2026
Domine o API Platform com Symfony para criar APIs REST de alto desempenho. Guia completo com instalação, configuração, boas práticas e perguntas de entrevista técnica.

O API Platform se consolidou como o framework de referência para desenvolver APIs REST profissionais com Symfony. Esta solução oferece produtividade excepcional enquanto respeita os padrões web modernos. Este tutorial aborda a instalação, configuração avançada e conceitos essenciais para se destacar em entrevistas técnicas.
O API Platform gera automaticamente documentação OpenAPI, suporte a JSON-LD/Hydra e GraphQL. Essas funcionalidades integradas aceleram consideravelmente o desenvolvimento de APIs em conformidade com os padrões.
Instalação do API Platform com Symfony
A instalação do API Platform em um projeto Symfony existente é realizada via Composer. O bundle se integra perfeitamente com o ecossistema Symfony e Doctrine.
composer require api-platform/corePara um novo projeto, o API Platform oferece uma distribuição completa incluindo Symfony, Docker e ferramentas de desenvolvimento pré-configuradas:
composer create-project api-platform/api-platform my-api
cd my-api
docker compose up -dA configuração mínima é feita no arquivo config/packages/api_platform.yaml:
api_platform:
title: 'Minha API REST'
version: '1.0.0'
formats:
jsonld: ['application/ld+json']
json: ['application/json']
docs_formats:
jsonld: ['application/ld+json']
jsonopenapi: ['application/vnd.openapi+json']
html: ['text/html']
defaults:
pagination_enabled: true
pagination_items_per_page: 30Criação de um Recurso API
A transformação de uma entidade Doctrine em recurso API é realizada com o atributo #[ApiResource]. O API Platform gera automaticamente as operações CRUD padrão.
<?php
namespace App\Entity;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\Put;
use ApiPlatform\Metadata\Delete;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Entity]
#[ApiResource(
operations: [
new GetCollection(),
new Post(),
new Get(),
new Put(),
new Delete()
],
paginationItemsPerPage: 20
)]
class Product
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
#[Assert\NotBlank]
#[Assert\Length(min: 3, max: 255)]
private string $name;
#[ORM\Column(type: 'text')]
private string $description;
#[ORM\Column(type: 'decimal', precision: 10, scale: 2)]
#[Assert\Positive]
private string $price;
#[ORM\Column]
private \DateTimeImmutable $createdAt;
public function __construct()
{
$this->createdAt = new \DateTimeImmutable();
}
// Getters e setters...
}Grupos de Serialização e DTO
O controle preciso dos dados expostos é realizado através de grupos de serialização. Esta abordagem permite diferenciar os campos visíveis de acordo com o contexto.
<?php
namespace App\Entity;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Post;
use Symfony\Component\Serializer\Annotation\Groups;
#[ApiResource(
operations: [
new GetCollection(normalizationContext: ['groups' => ['product:list']]),
new Get(normalizationContext: ['groups' => ['product:read']]),
new Post(denormalizationContext: ['groups' => ['product:write']])
]
)]
class Product
{
#[Groups(['product:list', 'product:read'])]
private ?int $id = null;
#[Groups(['product:list', 'product:read', 'product:write'])]
private string $name;
#[Groups(['product:read', 'product:write'])]
private string $description;
#[Groups(['product:list', 'product:read', 'product:write'])]
private string $price;
#[Groups(['product:read'])]
private \DateTimeImmutable $createdAt;
}Para casos complexos, os DTOs (Data Transfer Objects) oferecem uma separação clara entre a representação da API e o modelo de negócio:
<?php
namespace App\Dto;
use Symfony\Component\Validator\Constraints as Assert;
final class CreateProductInput
{
#[Assert\NotBlank]
#[Assert\Length(min: 3, max: 255)]
public string $name;
#[Assert\NotBlank]
public string $description;
#[Assert\Positive]
public float $price;
#[Assert\NotBlank]
public string $categoryId;
}Filtros e Busca Avançada
O API Platform integra um sistema de filtros poderoso para operações de coleção. Os filtros são aplicados diretamente nas entidades.
<?php
namespace App\Entity;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
use ApiPlatform\Doctrine\Orm\Filter\RangeFilter;
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
use ApiPlatform\Doctrine\Orm\Filter\DateFilter;
#[ApiResource]
#[ApiFilter(SearchFilter::class, properties: [
'name' => 'partial',
'category.name' => 'exact'
])]
#[ApiFilter(RangeFilter::class, properties: ['price'])]
#[ApiFilter(OrderFilter::class, properties: ['name', 'price', 'createdAt'])]
#[ApiFilter(DateFilter::class, properties: ['createdAt'])]
class Product
{
// Propriedades...
}As requisições HTTP utilizam esses filtros através de parâmetros de query string:
# Busca parcial por nome
GET /api/products?name=smartphone
# Filtragem por faixa de preços
GET /api/products?price[gte]=100&price[lte]=500
# Ordenação por preço decrescente
GET /api/products?order[price]=desc
# Combinação de filtros
GET /api/products?name=phone&price[gte]=200&order[createdAt]=descState Providers e State Processors
Os State Providers permitem personalizar a recuperação de dados, enquanto os State Processors controlam as operações de escrita.
<?php
namespace App\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use App\Repository\ProductRepository;
final class ProductStateProvider implements ProviderInterface
{
public function __construct(
private ProductRepository $repository
) {}
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
{
if (isset($uriVariables['id'])) {
return $this->repository->findActiveById($uriVariables['id']);
}
return $this->repository->findAllActive();
}
}O State Processor gerencia a lógica de negócio durante criações e modificações:
<?php
namespace App\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProcessorInterface;
use App\Entity\Product;
use App\Service\ProductService;
use App\Service\NotificationService;
final class ProductStateProcessor implements ProcessorInterface
{
public function __construct(
private ProcessorInterface $persistProcessor,
private ProductService $productService,
private NotificationService $notificationService
) {}
public function process(
mixed $data,
Operation $operation,
array $uriVariables = [],
array $context = []
): Product {
$this->productService->calculateFinalPrice($data);
$result = $this->persistProcessor->process($data, $operation, $uriVariables, $context);
if ($operation instanceof Post) {
$this->notificationService->notifyNewProduct($result);
}
return $result;
}
}Segurança e Controle de Acesso
O API Platform se integra com o componente Security do Symfony para gerenciar autenticação e autorizações.
<?php
namespace App\Entity;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\Put;
use ApiPlatform\Metadata\Delete;
#[ApiResource(
operations: [
new GetCollection(),
new Get(),
new Post(security: "is_granted('ROLE_ADMIN')"),
new Put(security: "is_granted('ROLE_ADMIN') or object.owner == user"),
new Delete(security: "is_granted('ROLE_ADMIN')")
]
)]
class Product
{
// ...
}Para segurança a nível de campos, os grupos de serialização combinados com voters oferecem controle granular:
<?php
namespace App\Serializer;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
final class ProductNormalizer implements NormalizerInterface
{
public function __construct(
private NormalizerInterface $normalizer,
private AuthorizationCheckerInterface $authChecker
) {}
public function normalize($object, ?string $format = null, array $context = []): array
{
$data = $this->normalizer->normalize($object, $format, $context);
if (!$this->authChecker->isGranted('ROLE_ADMIN')) {
unset($data['costPrice'], $data['margin']);
}
return $data;
}
public function supportsNormalization($data, ?string $format = null, array $context = []): bool
{
return $data instanceof Product;
}
}Pronto para mandar bem nas entrevistas de Symfony?
Pratique com nossos simuladores interativos, flashcards e testes tecnicos.
Perguntas de Entrevista sobre API Platform
As entrevistas técnicas sobre API Platform avaliam a compreensão dos conceitos fundamentais e boas práticas.
Pergunta: Qual a diferença entre State Provider e State Processor?
O State Provider recupera dados (operações GET), enquanto o State Processor os modifica (POST, PUT, PATCH, DELETE). Esta separação respeita o princípio de responsabilidade única.
Pergunta: Como implementar paginação personalizada?
#[ApiResource(
paginationEnabled: true,
paginationItemsPerPage: 20,
paginationMaximumItemsPerPage: 100,
paginationClientEnabled: true,
paginationClientItemsPerPage: true
)]Pergunta: Como lidar com relacionamentos no API Platform?
Os relacionamentos utilizam IRIs (Internationalized Resource Identifiers). Para incluir dados relacionados, configuram-se grupos de serialização apropriados ou utiliza-se a opção fetchEager.
Pergunta: Qual estratégia usar para versionamento de API?
O API Platform suporta várias abordagens: versionamento por URL (/api/v1/products), por header (Accept: application/vnd.api+json;version=1) ou por query parameter. A configuração é feita através de operações personalizadas.
Pergunta: Como otimizar o desempenho com API Platform?
As otimizações incluem: eager loading de relacionamentos, uso do cache HTTP integrado, paginação apropriada e grupos de serialização específicos para reduzir o tamanho das respostas.
Testes Funcionais de API
Os testes de API utilizam o cliente HTTP do Symfony combinado com asserções específicas do API Platform.
<?php
namespace App\Tests\Api;
use ApiPlatform\Symfony\Bundle\Test\ApiTestCase;
use App\Entity\Product;
use App\Factory\ProductFactory;
final class ProductApiTest extends ApiTestCase
{
public function testGetCollection(): void
{
ProductFactory::createMany(30);
$response = static::createClient()->request('GET', '/api/products');
$this->assertResponseIsSuccessful();
$this->assertJsonContains([
'@context' => '/api/contexts/Product',
'@type' => 'Collection',
'totalItems' => 30
]);
$this->assertCount(20, $response->toArray()['member']);
}
public function testCreateProduct(): void
{
$response = static::createClient()->request('POST', '/api/products', [
'json' => [
'name' => 'Novo Produto',
'description' => 'Descrição do produto',
'price' => '99.99'
],
'headers' => ['Content-Type' => 'application/ld+json']
]);
$this->assertResponseStatusCodeSame(201);
$this->assertJsonContains([
'@type' => 'Product',
'name' => 'Novo Produto'
]);
}
public function testFilterByPrice(): void
{
ProductFactory::createOne(['price' => '50.00']);
ProductFactory::createOne(['price' => '150.00']);
ProductFactory::createOne(['price' => '250.00']);
$response = static::createClient()->request(
'GET',
'/api/products?price[gte]=100&price[lte]=200'
);
$this->assertResponseIsSuccessful();
$this->assertCount(1, $response->toArray()['member']);
}
}Conclusão
O API Platform representa uma solução madura e de alto desempenho para desenvolver APIs REST com Symfony. O domínio dos conceitos de recursos, filtros, state providers/processors e segurança permite construir APIs robustas e de fácil manutenção. As perguntas de entrevista geralmente focam nesses fundamentos junto com as boas práticas de design de APIs RESTful.
Você saberia encontrar o bug em Symfony?
Um trecho real, um bug escondido, uma tentativa por dia. Sem conta para testar.

Escrito por
Anthony Fillion-MailletFundador da SharpSkill
Desenvolvedor fullstack há mais de 10 anos. Dirige a SharpSkill e responde por tudo o que é publicado aqui.
Atualizado em 25 de agosto de 2026
Compartilhar
Artigos relacionados

Seguranca de API REST no Symfony 2026: OAuth2, Rate Limiting e Perguntas de Entrevista
Guia completo sobre seguranca de API REST no Symfony com OAuth2, rate limiting, JWT e Voters. Inclui perguntas de entrevista tecnica.

API Platform com Symfony em 2026: Arquitetura, State Providers e Perguntas de Entrevista
Dominar API Platform 4.2 com Symfony: State Providers, Processors, Object Mapper, JSON Streamer para otimização de performance, e perguntas de entrevista técnica para desenvolvedores seniores.

API Platform GraphQL com Symfony: Schemas, Mutations e Perguntas de Entrevista 2026
Domine a integração do GraphQL no Symfony com API Platform. Este guia abrange schemas, mutations, resolvers personalizados e as perguntas de entrevista técnica mais frequentes em 2026.