Essayez sans attendre l'hébergement proposé par WordPress
-15% sur le premier mois avec le code 2025PRESS15AFF

Essayer maintenant

WPGraphQL : exploiter GraphQL avec WordPress pour vos projets headless

Vous en avez marre de récupérer vos données WordPress via des endpoints REST rigides qui renvoient soit trop d’infos, soit pas assez ? GraphQL propose une autre philosophie : une seule requête, exactement les champs dont on a besoin, et rien d’autre. Avec WPGraphQL, ce langage de requêtes s’installe en quelques minutes sur WordPress et ouvre la porte à des projets headless bien plus flexibles qu’avec l’API REST classique.

Installer et configurer WPGraphQL

Avant de plonger dans les requêtes et les schémas, il faut d’abord mettre en place l’outil qui va tout rendre possible. Bonne nouvelle : WPGraphQL est gratuit, disponible directement sur wordpress.org, et affiche plus de 100 000 installations actives. Un plugin mature, donc, activement maintenu par une communauté sérieuse. Voyons comment l’installer et le configurer sans prise de tête.

Installation du plugin et prérequis

Deux méthodes s’offrent à vous pour installer WPGraphQL. La première, la plus simple : direction l’administration WordPress, onglet « Extensions » puis « Ajouter », et vous recherchez « WPGraphQL ». Un clic sur « Installer », puis « Activer », et c’est réglé.

Si vous travaillez plutôt en mode développeur avec un projet géré via Composer (ce qui est fortement recommandé pour du headless), la commande composer require wp-graphql/wp-graphql fait le travail proprement, en intégrant le plugin dans vos dépendances versionnées.

Côté prérequis techniques, rien de bien contraignant : PHP 7.4 minimum (idéalement en 8.x pour de meilleures performances) et WordPress 5.0 ou supérieur. Une fois le plugin activé, vérifiez que tout fonctionne en accédant à l’URL votre-site.com/graphql. Vous devriez obtenir une réponse JSON, signe que l’endpoint répond bien. Si vous tombez sur une erreur 404, jetez un œil à vos permaliens (souvent le coupable dans ce genre de cas).

Découverte de l’IDE GraphiQL intégré

Une fois WPGraphQL activé, un nouveau menu apparaît dans votre admin WordPress : « GraphQL ». Et c’est là que se cache une pépite : l’IDE GraphiQL, intégré nativement au plugin. Concrètement, c’est une interface qui vous permet de tester vos requêtes en direct, sans écrire une seule ligne de code côté frontend.

L’interface se divise en deux panneaux : à gauche, vous écrivez votre requête, à droite, s’affiche la réponse. Un explorateur de schéma (accessible via l’icône dédiée) vous aide aussi à découvrir les champs disponibles, un peu comme une carte du territoire GraphQL de votre site.

Pour prendre en main l’outil, essayez cette requête toute simple, qui récupère le titre et l’extrait de vos derniers articles :

query {
  posts {
    nodes {
      title
      excerpt
    }
  }
}

Exécutez-la (bouton « play » ou raccourci Ctrl+Entrée), et vous devriez voir apparaître vos données instantanément. Pas mal, non ? C’est exactement ce genre d’expérimentation rapide qui rend GraphQL si agréable à utiliser au quotidien.

Manipuler les données avec des requêtes GraphQL

Maintenant qu’on a GraphiQL sous la main, on va passer aux choses sérieuses : écrire de vraies requêtes qui vont chercher exactement ce dont on a besoin. C’est là que WPGraphQL prend tout son sens face à l’API REST classique. Fini les endpoints multiples, place à une requête unique, bien construite.

Récupérer des articles, pages et médias

Chaque type de contenu WordPress possède son équivalent dans le schéma GraphQL : posts, pages, mediaItems. La syntaxe reste cohérente d’un type à l’autre, ce qui facilite grandement la prise en main.

Voici un exemple qui récupère les trois en une seule requête :

query GetContent {
  posts {
    nodes {
      id
      title
      slug
      featuredImage {
        node {
          sourceUrl
        }
      }
    }
  }
  pages {
    nodes {
      id
      title
      slug
    }
  }
  mediaItems {
    nodes {
      id
      title
      sourceUrl
      mimeType
    }
  }
}

Notez la structure nodes : c’est la convention GraphQL pour représenter une liste. Le champ featuredImage demande une sous-requête (imbriquée dans node), car l’image mise en avant est elle-même un objet complexe avec ses propres métadonnées. On ne récupère que les champs qu’on liste, rien de plus : pas de surcharge inutile de données.

Filtrer, paginer et trier les résultats

Ici, GraphQL diffère pas mal de l’API REST. Plutôt qu’une pagination par offset (page 1, page 2, etc.), WPGraphQL utilise la pagination par curseur, avec les arguments first et after. C’est plus robuste sur des contenus qui bougent souvent (un nouvel article publié ne décale pas toute votre pagination).

query GetPosts($after: String) {
  posts(
    first: 10
    after: $after
    where: { orderby: { field: DATE, order: DESC } }
  ) {
    pageInfo {
      hasNextPage
      endCursor
    }
    nodes {
      id
      title
      date
    }
  }
}

Le champ first limite le nombre de résultats, after prend le curseur renvoyé par la requête précédente (endCursor). L’argument where permet de filtrer (par catégorie, statut, auteur…) et de trier via orderby. Pratique pour construire un scroll infini côté frontend, sans se soucier des décalages d’index.

Requêtes imbriquées et relations entre types

C’est probablement l’argument numéro un en faveur de GraphQL sur ce type de projet headless. En REST, récupérer un article avec son auteur, ses catégories et ses commentaires nécessite plusieurs appels, ou l’usage de _embed (avec ses limites en termes de contrôle sur les données renvoyées). En GraphQL, tout se fait en une seule requête, imbriquée intelligemment.

query GetPostWithRelations {
  post(id: "123", idType: DATABASE_ID) {
    title
    content
    author {
      node {
        name
        avatar {
          url
        }
      }
    }
    categories {
      nodes {
        name
        slug
      }
    }
    comments {
      nodes {
        content
        author {
          node {
            name
          }
        }
      }
    }
  }
}

Chaque relation (auteur, catégories, commentaires) est un simple champ imbriqué. Le client décide de la profondeur des données qu’il veut charger. Résultat : moins d’appels réseau, un frontend plus rapide, et un code d’intégration nettement plus lisible.

Mutations : créer et modifier du contenu

Les requêtes (queries) servent à lire, mais GraphQL permet aussi d’écrire via les mutations. Pour créer un article par exemple, on utilise createPost. Attention cependant : cette opération nécessite une authentification, WordPress ne laisse pas n’importe qui publier du contenu (heureusement !).

C’est là qu’intervient le plugin wp-graphql-jwt-authentication, qui ajoute la gestion des tokens JWT au schéma. Une fois installé, on récupère un token via une mutation de login, puis on l’inclut dans le header Authorization de chaque requête suivante.

mutation CreateNewPost {
  createPost(
    input: {
      title: "Mon nouvel article"
      content: "Contenu rédigé via GraphQL"
      status: PUBLISH
    }
  ) {
    post {
      id
      title
      slug
    }
  }
}

Le champ input regroupe tous les paramètres de création : titre, contenu, statut de publication (PUBLISH, DRAFT…). En retour, on demande les champs qu’on souhaite récupérer sur le post créé. La logique est la même pour updatePost ou deletePost : on manipule le contenu WordPress sans jamais quitter l’écosystème GraphQL.

Enregistrer des champs personnalisés pour l’API GraphQL

Par défaut, WPGraphQL expose les champs natifs de WordPress (titre, contenu, date, auteur…). Mais dans la plupart des projets headless, on a besoin d’exposer aussi ses propres données : champs ACF, meta personnalisés, ou Custom Post Types. Bonne nouvelle : WPGraphQL a été pensé pour être extensible, et l’API qu’il propose pour ça reste simple à prendre en main.

Exposer un champ ACF ou un custom field via register_graphql_field

Si vous utilisez Advanced Custom Fields (ACF), le plus simple reste d’installer le plugin WPGraphQL for ACF : il détecte automatiquement vos groupes de champs et les expose dans le schéma, sans écrire une seule ligne de code. Pratique quand on a beaucoup de champs à gérer.

Mais si vous voulez garder la main sur ce qui est exposé (ou que vous n’utilisez pas ACF), vous pouvez enregistrer un champ manuellement avec register_graphql_field(), à appeler dans le hook graphql_register_types :

add_action( 'graphql_register_types', function() {
    register_graphql_field( 'Post', 'sousTitre', [
        'type'        => 'String',
        'description' => __( 'Sous-titre personnalisé de l\'article', 'mon-theme' ),
        'resolve'     => function( $post ) {
            return get_post_meta( $post->ID, 'sous_titre', true );
        }
    ] );
} );

Ici, on ajoute un champ sousTitre au type Post existant. Le callback resolve va simplement chercher la valeur dans les metas via get_post_meta(). Notez le nom en camelCase côté GraphQL (sousTitre) alors que la meta key WordPress reste en snake_case (sous_titre) : c’est une convention à respecter pour rester cohérent avec le reste du schéma.

Créer un type GraphQL personnalisé pour un Custom Post Type

Pour qu’un Custom Post Type soit visible dans l’API, il faut le déclarer explicitement lors de son enregistrement. Trois arguments sont indispensables dans register_post_type() :

add_action( 'init', function() {
    register_post_type( 'produit', [
        'label'              => 'Produits',
        'public'             => true,
        'show_in_rest'       => true,
        'supports'           => [ 'title', 'editor', 'thumbnail' ],
        'show_in_graphql'    => true,
        'graphql_single_name' => 'produit',
        'graphql_plural_name' => 'produits',
    ] );
} );

graphql_single_name et graphql_plural_name définissent respectivement le nom du type unique (produit) et celui utilisé pour les requêtes en liste (produits). Ces noms doivent aussi être en camelCase si votre CPT a un slug composé (par exemple produitPhare plutôt que produit_phare), sinon WPGraphQL renvoie une erreur au moment de générer le schéma.

Une fois le CPT enregistré, on peut lui ajouter des champs custom exactement comme pour les posts classiques, en ciblant le type généré :

add_action( 'graphql_register_types', function() {
    register_graphql_field( 'Produit', 'prix', [
        'type'    => 'Float',
        'resolve' => function( $post ) {
            return (float) get_post_meta( $post->ID, 'prix', true );
        }
    ] );
} );

Petit rappel qui évite bien des prises de tête : après chaque modification de schéma (nouveau champ, nouveau CPT), il faut vider le cache du schéma GraphQL. Ça se fait dans GraphQL > Settings, via le bouton dédié. Sans ça, vos changements n’apparaîtront pas dans GraphiQL, et vous risquez de perdre du temps à chercher un bug qui n’existe pas !

GraphQL vs REST API : quel choix pour votre projet WordPress headless

Maintenant qu’on a vu comment configurer WPGraphQL, exposer des champs personnalisés et manipuler des requêtes complexes, une question légitime se pose : pourquoi ne pas simplement utiliser l’API REST native de WordPress ? Bonne question, et honnêtement, il n’y a pas de mauvaise réponse : les deux approches ont leurs forces. Voyons ça objectivement.

Avantages et limites de chaque approche

Côté GraphQL, l’atout principal, c’est la flexibilité des requêtes : on récupère exactement les données dont on a besoin, en une seule requête, même si elles sont imbriquées (un article avec son auteur, ses catégories et ses commentaires, par exemple). Fini l’over-fetching (récupérer trop de données) ou l’under-fetching (devoir enchaîner plusieurs appels). Le typage fort du schéma est aussi un vrai plus : on sait précisément ce qu’on peut demander, et l’introspection permet d’explorer l’API sans documentation externe.

Mais GraphQL a ses contraintes. La mise en cache HTTP classique (basée sur les URLs) devient plus complexe, puisque toutes les requêtes passent par le même endpoint. On peut aussi rencontrer des problèmes de requêtes N+1 côté serveur si le resolver n’est pas optimisé. Et la courbe d’apprentissage du langage de requête peut freiner certains développeurs au démarrage.

L’API REST, elle, mise sur la simplicité : des URLs prévisibles, un écosystème mature (Postman fonctionne nativement sans configuration particulière), et une mise en cache HTTP native beaucoup plus simple à mettre en place. Par contre, pour des données liées, il faut souvent multiplier les appels, ce qui peut vite devenir lourd (et générer de l’over-fetching, puisque chaque endpoint renvoie généralement toute la structure de l’objet).

Cas d’usage concrets : quand privilégier l’un ou l’autre

Dans la pratique, le choix dépend surtout de la complexité de votre frontend. Pour un projet Next.js ou Nuxt qui consomme WordPress en headless, avec des pages nécessitant plusieurs types de contenus liés (articles, taxonomies, auteurs, champs ACF), GraphQL simplifie énormément la récupération des données. Une requête bien construite suffit pour hydrater le composant.

À l’inverse, pour un site plus simple, ou une intégration rapide où on n’a pas besoin de données ultra-imbriquées, l’API REST reste largement suffisante. Elle est plus rapide à mettre en place (pas besoin d’installer WPGraphQL, tout est déjà natif dans WordPress) et demande moins de configuration côté frontend. Si vous testez un MVP ou un petit prototype, ça peut faire gagner un temps précieux.

Et d’ailleurs, rien n’empêche de faire cohabiter les deux API sur un même projet ! On peut très bien utiliser REST pour des besoins simples (récupérer une liste d’articles récents, par exemple) et GraphQL pour des pages plus complexes nécessitant des données croisées. WordPress ne vous impose aucun choix exclusif : c’est vous qui décidez selon les besoins réels de chaque fonctionnalité.