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.

API Platform GraphQL com Symfony: Schemas, Mutations e Perguntas de Entrevista 2026

A integração do GraphQL em aplicações Symfony representa uma evolução significativa no design de APIs modernas. O API Platform simplifica consideravelmente essa integração ao oferecer geração automática de schemas GraphQL a partir de entidades Doctrine. Este tutorial explora em profundidade os conceitos essenciais para dominar o API Platform GraphQL em um contexto Symfony.

O API Platform 4.0 introduz melhorias significativas para GraphQL, incluindo melhor gerenciamento de subscriptions e desempenho otimizado para consultas complexas.

Instalação e Configuração Inicial

A instalação do GraphQL em um projeto API Platform requer algumas dependências específicas. A biblioteca webonyx/graphql-php constitui o motor principal de execução GraphQL.

bash
composer require api-platform/graphql

A configuração é realizada no arquivo de configuração do API Platform. A ativação do GraphQL expõe automaticamente um endpoint dedicado.

yaml
# config/packages/api_platform.yaml
api_platform:
    graphql:
        enabled: true
        graphiql:
            enabled: true
        introspection:
            enabled: true

Essa configuração ativa o GraphiQL, a interface interativa que permite explorar e testar consultas GraphQL diretamente pelo navegador.

Definição de Schemas GraphQL

Os schemas GraphQL no API Platform são gerados automaticamente a partir dos atributos PHP definidos nas entidades. Cada recurso API se torna um tipo GraphQL com seus campos correspondentes.

php
<?php

namespace App\Entity;

use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\GraphQl\Query;
use ApiPlatform\Metadata\GraphQl\QueryCollection;
use ApiPlatform\Metadata\GraphQl\Mutation;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity]
#[ApiResource(
    graphQlOperations: [
        new Query(),
        new QueryCollection(),
        new Mutation(name: 'create'),
        new Mutation(name: 'update'),
        new Mutation(name: 'delete'),
    ]
)]
class Article
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 255)]
    private string $title;

    #[ORM\Column(type: 'text')]
    private string $content;

    #[ORM\Column]
    private \DateTimeImmutable $publishedAt;

    // Getters e setters...
}

Essa definição gera automaticamente os tipos GraphQL correspondentes, incluindo os tipos de entrada para mutations e os tipos de saída para consultas.

Consultas GraphQL Avançadas

As consultas GraphQL permitem recuperar exatamente os dados necessários. O API Platform suporta filtros, paginação e ordenação diretamente nas consultas GraphQL.

graphql
query GetArticles {
  articles(first: 10, after: "cursor123", order: { publishedAt: "DESC" }) {
    edges {
      node {
        id
        title
        content
        publishedAt
      }
      cursor
    }
    pageInfo {
      hasNextPage
      endCursor
    }
    totalCount
  }
}

A paginação utiliza o padrão Relay Connection, oferecendo navegação eficiente através de coleções de dados volumosas.

Mutations e Validação

As mutations permitem modificar dados no servidor. O API Platform integra automaticamente a validação do Symfony no processo de mutation.

php
<?php

namespace App\Entity;

use Symfony\Component\Validator\Constraints as Assert;

#[ORM\Entity]
#[ApiResource(
    graphQlOperations: [
        new Mutation(
            name: 'create',
            validationContext: ['groups' => ['create']]
        ),
        new Mutation(
            name: 'update',
            validationContext: ['groups' => ['update']]
        ),
    ]
)]
class Article
{
    #[Assert\NotBlank(groups: ['create', 'update'])]
    #[Assert\Length(min: 5, max: 255, groups: ['create', 'update'])]
    private string $title;

    #[Assert\NotBlank(groups: ['create'])]
    private string $content;
}

A execução de uma mutation com dados inválidos retorna erros estruturados conforme a especificação GraphQL.

graphql
mutation CreateArticle {
  createArticle(input: {
    title: "Novo título do artigo"
    content: "Conteúdo detalhado do artigo..."
  }) {
    article {
      id
      title
    }
  }
}

Resolvers Personalizados

Para casos de uso complexos, o API Platform permite definir resolvers personalizados. Esses resolvers interceptam a execução padrão e implementam lógica de negócio específica.

php
<?php

namespace App\Resolver;

use ApiPlatform\GraphQl\Resolver\QueryItemResolverInterface;
use App\Entity\Article;
use App\Repository\ArticleRepository;

class ArticleBySlugResolver implements QueryItemResolverInterface
{
    public function __construct(
        private ArticleRepository $repository
    ) {}

    public function __invoke(?object $item, array $context): ?Article
    {
        $slug = $context['args']['slug'] ?? null;
        
        if ($slug === null) {
            return null;
        }

        return $this->repository->findOneBySlug($slug);
    }
}

O registro do resolver é feito através do atributo GraphQl\Query com o parâmetro resolver.

php
#[ApiResource(
    graphQlOperations: [
        new Query(
            name: 'bySlug',
            resolver: ArticleBySlugResolver::class,
            args: ['slug' => ['type' => 'String!']]
        ),
    ]
)]
class Article
{
    // ...
}

Gerenciamento de Relacionamentos

Os relacionamentos entre entidades são automaticamente expostos no schema GraphQL. O API Platform gerencia relacionamentos OneToMany, ManyToOne e ManyToMany de forma transparente.

php
<?php

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;

#[ORM\Entity]
#[ApiResource]
class Author
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 255)]
    private string $name;

    #[ORM\OneToMany(mappedBy: 'author', targetEntity: Article::class)]
    private Collection $articles;

    public function __construct()
    {
        $this->articles = new ArrayCollection();
    }
}

As consultas GraphQL podem atravessar esses relacionamentos para recuperar dados aninhados em uma única requisição.

graphql
query GetAuthorWithArticles {
  author(id: "/authors/1") {
    name
    articles {
      edges {
        node {
          title
          publishedAt
        }
      }
    }
  }
}

Segurança e Autorização

A segurança das operações GraphQL utiliza o sistema de segurança do Symfony. As expressões de segurança podem ser definidas no nível das operações.

php
#[ApiResource(
    graphQlOperations: [
        new Query(
            security: "is_granted('ROLE_USER')"
        ),
        new Mutation(
            name: 'create',
            security: "is_granted('ROLE_ADMIN')"
        ),
        new Mutation(
            name: 'update',
            security: "is_granted('ROLE_ADMIN') or object.getAuthor() == user"
        ),
    ]
)]
class Article
{
    // ...
}

Tentativas de acesso não autorizado geram erros GraphQL apropriados com os códigos de erro correspondentes.

Otimização de Desempenho

Consultas GraphQL complexas podem gerar o problema N+1. O API Platform integra mecanismos de otimização automática através de extensões Doctrine.

php
<?php

namespace App\Extension;

use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface;
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use App\Entity\Article;
use Doctrine\ORM\QueryBuilder;

class ArticleEagerLoadingExtension implements QueryCollectionExtensionInterface
{
    public function applyToCollection(
        QueryBuilder $queryBuilder,
        QueryNameGeneratorInterface $queryNameGenerator,
        string $resourceClass,
        ?string $operationName = null,
        array $context = []
    ): void {
        if ($resourceClass !== Article::class) {
            return;
        }

        $rootAlias = $queryBuilder->getRootAliases()[0];
        $queryBuilder
            ->leftJoin(sprintf('%s.author', $rootAlias), 'a')
            ->addSelect('a');
    }
}

Pronto para mandar bem nas entrevistas de Symfony?

Pratique com nossos simuladores interativos, flashcards e testes tecnicos.

Perguntas de Entrevista GraphQL API Platform

As entrevistas técnicas em 2026 incluem frequentemente perguntas sobre GraphQL e API Platform. A seguir estão as perguntas mais relevantes.

Pergunta: Qual é a diferença entre uma Query e uma Mutation no GraphQL?

Queries são operações de leitura idempotentes que não modificam o estado do servidor. Mutations são operações de escrita que podem criar, modificar ou excluir dados. O GraphQL garante que as Mutations sejam executadas sequencialmente enquanto as Queries podem ser executadas em paralelo.

Pergunta: Como o API Platform gera o schema GraphQL?

O API Platform utiliza a introspecção de metadados PHP (atributos ApiResource) e os mapeamentos do Doctrine para gerar automaticamente o schema GraphQL. Os tipos, campos e relacionamentos são deduzidos das entidades e suas propriedades.

Pergunta: Como é gerenciada a paginação no GraphQL com API Platform?

O API Platform implementa a especificação Relay Connection para paginação. As coleções retornam objetos com edges (contendo nodes e cursors), pageInfo (hasNextPage, hasPreviousPage, cursors) e totalCount. Os argumentos first, last, before e after controlam a navegação.

Pergunta: Como proteger uma mutation GraphQL?

A proteção utiliza o atributo security na operação Mutation. As expressões de segurança do Symfony (is_granted, object.owner == user) permitem controle de acesso granular. Voters personalizados também podem ser utilizados para lógicas de autorização complexas.

Pergunta: O que é o problema N+1 e como resolvê-lo?

O problema N+1 ocorre quando uma consulta inicial é seguida por N consultas adicionais para carregar relacionamentos. No API Platform, as extensões Doctrine permitem adicionar joins e eager loading. O padrão DataLoader também pode ser implementado para agrupar consultas.

Pergunta: Como criar um resolver personalizado?

Um resolver personalizado implementa QueryItemResolverInterface ou MutationResolverInterface. É registrado através do atributo GraphQl\Query ou GraphQl\Mutation com o parâmetro resolver apontando para a classe do serviço.

Conclusão

A integração do GraphQL no Symfony através do API Platform oferece uma solução robusta para construir APIs flexíveis e de alto desempenho. A geração automática de schemas, combinada com as possibilidades de personalização avançadas, permite atender às exigências de aplicações modernas. O domínio desses conceitos constitui uma vantagem considerável para desenvolvedores Symfony em 2026, tanto em projetos profissionais quanto em entrevistas técnicas.

Desafio do dia

Você saberia encontrar o bug em Symfony?

Um trecho real, um bug escondido, uma tentativa por dia. Sem conta para testar.

Anthony Fillion-Maillet

Escrito por

Anthony Fillion-Maillet

Fundador da SharpSkill

Desenvolvedor fullstack há mais de 10 anos. Dirige a SharpSkill e responde por tudo o que é publicado aqui.

Atualizado em 27 de agosto de 2026

Compartilhar

Artigos relacionados