API Platform GraphQL con Symfony: Esquemas, Mutaciones y Preguntas de Entrevista 2026

Domina la integración de GraphQL en Symfony con API Platform. Esta guía cubre esquemas, mutaciones, resolvers personalizados y las preguntas de entrevista técnica más frecuentes en 2026.

API Platform GraphQL con Symfony: Esquemas, Mutaciones y Preguntas de Entrevista 2026

La integración de GraphQL en aplicaciones Symfony representa una evolución significativa en el diseño de APIs modernas. API Platform simplifica considerablemente esta integración al ofrecer generación automática de esquemas GraphQL a partir de entidades Doctrine. Este tutorial explora en profundidad los conceptos esenciales para dominar API Platform GraphQL en un contexto Symfony.

API Platform 4.0 introduce mejoras significativas para GraphQL, incluyendo una mejor gestión de subscriptions y rendimiento optimizado para consultas complejas.

Instalación y Configuración Inicial

La instalación de GraphQL en un proyecto API Platform requiere algunas dependencias específicas. La biblioteca webonyx/graphql-php constituye el motor principal de ejecución GraphQL.

bash
composer require api-platform/graphql

La configuración se realiza en el archivo de configuración de API Platform. La activación de GraphQL expone automáticamente un endpoint dedicado.

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

Esta configuración activa GraphiQL, la interfaz interactiva que permite explorar y probar consultas GraphQL directamente desde el navegador.

Definición de Esquemas GraphQL

Los esquemas GraphQL en API Platform se generan automáticamente a partir de los atributos PHP definidos en las entidades. Cada recurso API se convierte en un tipo GraphQL con sus campos correspondientes.

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 y setters...
}

Esta definición genera automáticamente los tipos GraphQL correspondientes, incluyendo los tipos de entrada para mutaciones y los tipos de salida para consultas.

Consultas GraphQL Avanzadas

Las consultas GraphQL permiten recuperar exactamente los datos necesarios. API Platform soporta filtros, paginación y ordenamiento directamente en las consultas GraphQL.

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

La paginación utiliza el estándar Relay Connection, ofreciendo navegación eficiente a través de colecciones de datos voluminosas.

Mutaciones y Validación

Las mutaciones permiten modificar datos en el servidor. API Platform integra automáticamente la validación de Symfony en el proceso de mutación.

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;
}

La ejecución de una mutación con datos inválidos retorna errores estructurados conforme a la especificación GraphQL.

graphql
mutation CreateArticle {
  createArticle(input: {
    title: "Nuevo título del artículo"
    content: "Contenido detallado del artículo..."
  }) {
    article {
      id
      title
    }
  }
}

Resolvers Personalizados

Para casos de uso complejos, API Platform permite definir resolvers personalizados. Estos resolvers interceptan la ejecución estándar e implementan lógica de negocio 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);
    }
}

El registro del resolver se realiza mediante el atributo GraphQl\Query con el parámetro resolver.

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

Gestión de Relaciones

Las relaciones entre entidades se exponen automáticamente en el esquema GraphQL. API Platform maneja las relaciones OneToMany, ManyToOne y ManyToMany de manera 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();
    }
}

Las consultas GraphQL pueden atravesar estas relaciones para recuperar datos anidados en una sola solicitud.

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

Seguridad y Autorización

La segurización de operaciones GraphQL utiliza el sistema de seguridad de Symfony. Las expresiones de seguridad pueden definirse a nivel de operaciones.

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
{
    // ...
}

Los intentos de acceso no autorizado generan errores GraphQL apropiados con los códigos de error correspondientes.

Optimización del Rendimiento

Las consultas GraphQL complejas pueden generar el problema N+1. API Platform integra mecanismos de optimización automática mediante extensiones 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');
    }
}

¿Listo para aprobar tus entrevistas de Symfony?

Practica con nuestros simuladores interactivos, flashcards y tests técnicos.

Preguntas de Entrevista GraphQL API Platform

Las entrevistas técnicas en 2026 incluyen frecuentemente preguntas sobre GraphQL y API Platform. A continuación se presentan las preguntas más relevantes.

Pregunta: ¿Cuál es la diferencia entre una Query y una Mutation en GraphQL?

Las Queries son operaciones de lectura idempotentes que no modifican el estado del servidor. Las Mutations son operaciones de escritura que pueden crear, modificar o eliminar datos. GraphQL garantiza que las Mutations se ejecuten secuencialmente mientras que las Queries pueden ejecutarse en paralelo.

Pregunta: ¿Cómo genera API Platform el esquema GraphQL?

API Platform utiliza la introspección de metadatos PHP (atributos ApiResource) y los mappings de Doctrine para generar automáticamente el esquema GraphQL. Los tipos, campos y relaciones se deducen de las entidades y sus propiedades.

Pregunta: ¿Cómo se gestiona la paginación en GraphQL con API Platform?

API Platform implementa la especificación Relay Connection para paginación. Las colecciones retornan objetos con edges (conteniendo nodes y cursors), pageInfo (hasNextPage, hasPreviousPage, cursors) y totalCount. Los argumentos first, last, before y after controlan la navegación.

Pregunta: ¿Cómo se asegura una mutación GraphQL?

La segurización utiliza el atributo security en la operación Mutation. Las expresiones de seguridad de Symfony (is_granted, object.owner == user) permiten control de acceso granular. Los voters personalizados también pueden utilizarse para lógicas de autorización complejas.

Pregunta: ¿Qué es el problema N+1 y cómo se resuelve?

El problema N+1 ocurre cuando una consulta inicial es seguida por N consultas adicionales para cargar relaciones. En API Platform, las extensiones Doctrine permiten agregar joins y eager loading. El patrón DataLoader también puede implementarse para agrupar consultas.

Pregunta: ¿Cómo se crea un resolver personalizado?

Un resolver personalizado implementa QueryItemResolverInterface o MutationResolverInterface. Se registra mediante el atributo GraphQl\Query o GraphQl\Mutation con el parámetro resolver apuntando a la clase del servicio.

Conclusión

La integración de GraphQL en Symfony mediante API Platform ofrece una solución robusta para construir APIs flexibles y de alto rendimiento. La generación automática de esquemas, combinada con las posibilidades de personalización avanzadas, permite responder a las exigencias de aplicaciones modernas. El dominio de estos conceptos constituye una ventaja considerable para desarrolladores Symfony en 2026, tanto en proyectos profesionales como en entrevistas técnicas.

Reto diario

¿Sabrías detectar el bug en Symfony?

Un fragmento real, un bug oculto, un intento al día. Sin cuenta para probar.

Anthony Fillion-Maillet

Escrito por

Anthony Fillion-Maillet

Fundador de SharpSkill

Desarrollador fullstack desde hace más de 10 años. Dirige SharpSkill y responde por todo lo que se publica aquí.

Actualizado el 27 de agosto de 2026

Compartir

Artículos relacionados