← Tous les articles >
magento 2magento developmentphpe-commerceadobe-commercetutorialmodule-development

Magento 2 GraphQL API : Guide du développeur complet (2026)

Share: LinkedIn X Facebook

L’API GraphQL de Magento 2 est le pilier des vitrines headless modernes, des PWA et des applications mobiles. Contrairement à REST — qui nécessite souvent plusieurs allers-retours — GraphQL permet à un client de demander exactement les champs dont il a besoin en un seul appel. Ce guide couvre le schéma intégré, l’authentification, les mutations de panier et de checkout, le développement de résolveurs personnalisés et les modèles de performance qui comptent en production.

En résumé : GraphQL dans Magento 2 expose les produits, catégories, panier, checkout et données clients via un schéma typé à /graphql. Utilisez les queries pour la lecture, les mutations pour l’écriture, et étendez le schéma avec des résolveurs personnalisés lorsque les champs intégrés ne suffisent pas.

Table des matières

  1. Pourquoi GraphQL pour Magento 2 ?
  2. Endpoint, en-têtes et première requête
  3. Schéma de base : produits, catégories, recherche
  4. Mutations de panier et checkout
  5. Authentification client
  6. Construction d’un résolveur de requête personnalisé
  7. Construction d’une mutation personnalisée
  8. Performance et mise en cache
  9. GraphQL vs REST : quand utiliser quoi
  10. FAQ technique

Pourquoi GraphQL pour Magento 2 ?

Adobe a massivement investi dans GraphQL comme API principale pour les opérations côté vitrine. REST reste disponible pour les intégrations Admin et les systèmes legacy, mais les nouveaux travaux frontend — Hyvä React Checkout, PWA Studio, vitrines Next.js personnalisées — fonctionnent sur GraphQL.

AvantageDétail
Requête uniqueRécupérez nom, prix, image et stock d’un produit en un appel
Pas de sur-récupérationLe client sélectionne uniquement les champs qu’il affiche
Schéma typéAuto-documenté via l’introspection
État du panierLe modèle de token cart_id convient aux frontends sans état
Stabilité des versionsLe schéma évolue avec des dépréciations rétrocompatibles

Endpoint :

POST https://your-store.com/graphql
Content-Type: application/json

Endpoint, en-têtes et première requête

Requête de produit de base

{
  products(filter: { sku: { eq: "24-MB01" } }) {
    items {
      sku
      name
      price_range {
        minimum_price {
          regular_price {
            value
            currency
          }
        }
      }
      image {
        url
        label
      }
    }
  }
}

Envoyez-la avec curl :

curl -X POST https://your-store.com/graphql \
  -H "Content-Type: application/json" \
  -d '{"query": "{ products(filter: { sku: { eq: \"24-MB01\" } }) { items { sku name } } }"}'

En-tête Store (configurations multi-boutiques)

Lorsque vous utilisez plusieurs vues de boutique, passez l’en-tête Store :

-H "Store: default"

Sans cela, Magento peut renvoyer des données de la mauvaise vue de boutique — mauvais prix, mauvaise langue, mauvaise devise.


Schéma de base : produits, catégories, recherche

Liste des catégories avec filtres

{
  categoryList(filters: { url_key: { eq: "gear" } }) {
    id
    name
    products(pageSize: 12, currentPage: 1) {
      total_count
      items {
        sku
        name
        small_image { url }
        price_range {
          minimum_price {
            final_price { value currency }
          }
        }
      }
      page_info {
        current_page
        total_pages
      }
    }
  }
}

Recherche en texte intégral

{
  products(search: "backpack", pageSize: 10) {
    total_count
    items {
      sku
      name
      url_key
    }
  }
}

La recherche repose sur l’indexeur catalogsearch_fulltext et Elasticsearch/OpenSearch. Si la recherche ne renvoie aucun résultat, réindexez d’abord :

bin/magento indexer:reindex catalogsearch_fulltext

Options de produit configurable

{
  products(filter: { sku: { eq: "MH01" } }) {
    items {
      sku
      name
      ... on ConfigurableProduct {
        configurable_options {
          attribute_code
          label
          values {
            value_index
            label
          }
        }
        variants {
          product {
            sku
            name
            price_range {
              minimum_price {
                final_price { value }
              }
            }
          }
        }
      }
    }
  }
}

Utilisez les fragments inline (... on ConfigurableProduct) pour accéder aux champs spécifiques au type — un modèle GraphQL de base dans Magento.


Mutations de panier et checkout

Les paniers invités utilisent un cart_id (identifiant de devis masqué). Les paniers clients utilisent le token client authentifié.

Créer un panier invité

mutation {
  createEmptyCart
}

Réponse :

{ "data": { "createEmptyCart": "abc123xyz" } }

Ajouter un produit au panier

mutation {
  addProductsToCart(
    cartId: "abc123xyz"
    cartItems: [{ sku: "24-MB01", quantity: 1 }]
  ) {
    cart {
      items {
        quantity
        product {
          name
          sku
        }
      }
      prices {
        grand_total {
          value
          currency
        }
      }
    }
  }
}

Fusionner le panier invité après connexion

mutation {
  mergeCarts(
    source_cart_id: "abc123xyz"
    destination_cart_id: "customer-cart-id"
  ) {
    items { quantity product { sku } }
  }
}

Définir l’adresse de livraison et le mode d’expédition

mutation {
  setShippingAddressesOnCart(
    input: {
      cart_id: "abc123xyz"
      shipping_addresses: [{
        address: {
          firstname: "John"
          lastname: "Doe"
          street: ["123 Main St"]
          city: "Paris"
          postcode: "75001"
          country_code: FR
          telephone: "0600000000"
        }
      }]
    }
  ) {
    cart {
      shipping_addresses {
        available_shipping_methods {
          carrier_code
          method_code
          amount { value currency }
        }
      }
    }
  }
}

Astuce checkout headless : Demandez toujours available_shipping_methods et available_payment_methods après avoir défini l’adresse — les tarifs dépendent du contenu du panier et de la destination.


Authentification client

Générer un token client

mutation {
  generateCustomerToken(
    email: "[email protected]"
    password: "Password123!"
  ) {
    token
  }
}

Utilisez le token dans les requêtes suivantes :

-H "Authorization: Bearer <token>"

Les tokens expirent selon la configuration Admin (Stores → Configuration → Services → OAuth → Customer Token Lifetime). La valeur par défaut est 1 heure — planifiez la logique de rafraîchissement dans votre frontend.

Requête d’introspection (dev uniquement)

Désactivez l’introspection en production pour des raisons de sécurité. En développement, explorez le schéma :

{
  __schema {
    types {
      name
      kind
    }
  }
}

Ou utilisez GraphQL Playground / Altair / Postman avec l’introspection activée.


Construction d’un résolveur de requête personnalisé

Lorsque le schéma intégré ne suffit pas, étendez-le avec un module personnalisé.

Structure du répertoire

app/code/MagentoMastery/GraphQlDemo/
├── registration.php
├── etc/
│   ├── module.xml
│   └── schema.graphqls
└── Model/
    └── Resolver/
        └── HelloWorld.php

Query schema.graphqls

type Query {
    helloWorld(name: String): String
      @resolver(class: "MagentoMastery\\GraphQlDemo\\Model\\Resolver\\HelloWorld")
      @doc(description: "Returns a greeting string")
}

Classe résolveur

<?php
declare(strict_types=1);

namespace MagentoMastery\GraphQlDemo\Model\Resolver;

use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;

class HelloWorld implements ResolverInterface
{
    public function resolve(
        Field $field,
        $context,
        ResolveInfo $info,
        ?array $value = null,
        ?array $args = null
    ): string {
        $name = $args['name'] ?? 'World';
        return "Hello, {$name}!";
    }
}

Tester la requête personnalisée

{ helloWorld(name: "Magento") }

Après le déploiement :

bin/magento setup:upgrade
bin/magento cache:flush

Les modifications du schéma GraphQL nécessitent une vidange du cache — Magento met en cache le schéma compilé.


Construction d’une mutation personnalisée

Les mutations suivent le même modèle mais implémentent ResolverInterface sur un champ de type Mutation.

Mutation schema.graphqls

type Mutation {
    subscribeNewsletter(email: String!): NewsletterOutput
      @resolver(class: "MagentoMastery\\GraphQlDemo\\Model\\Resolver\\SubscribeNewsletter")
}

type NewsletterOutput {
    success: Boolean!
    message: String
}

Résolveur avec validation

<?php
declare(strict_types=1);

namespace MagentoMastery\GraphQlDemo\Model\Resolver;

use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;

class SubscribeNewsletter implements ResolverInterface
{
    public function resolve(
        Field $field,
        $context,
        ResolveInfo $info,
        ?array $value = null,
        ?array $args = null
    ): array {
        $email = $args['email'] ?? '';

        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new GraphQlInputException(__('Adresse e-mail invalide.'));
        }

        // Subscribe logic here...

        return [
            'success' => true,
            'message' => 'Subscribed successfully.',
        ];
    }
}

Lancez GraphQlInputException pour les erreurs client (niveau 400) et GraphQlAuthorizationException pour les échecs d’authentification — Magento les traduit en réponses d’erreur GraphQL appropriées.


Performance et mise en cache

GraphQL peut être plus lent que prévu si les clients demandent trop de champs imbriqués. Appliquez ces règles en production :

1. Limiter la profondeur et la complexité des requêtes

Utilisez un proxy inverse ou les limites de complexité de requêtes intégrées de Magento (Adobe Commerce) pour bloquer les requêtes abusives.

2. Mettre en cache au CDN pour les requêtes anonymes

Ne mettez en cache que les requêtes qui n’incluent pas de tokens client ou d’ID de panier. Les requêtes de liste de produits sont de bons candidats CDN lorsqu’elles sont indexées par boutique + hash de requête.

3. Éviter le N+1 dans les résolveurs personnalisés

Lors de la résolution de listes, utilisez des résolveurs par lots ou des data loaders. Un résolveur naïf qui charge un modèle de produit par élément détruira les performances sur les pages de catégories.

4. Ne demander que ce que vous affichez

items { sku name description { html } }

items { sku name small_image { url } price_range { minimum_price { final_price { value } } } }

5. Maintenir les indexeurs à jour

GraphQL lit à partir de tables plates indexées et d’Elasticsearch. Des indexeurs obsolètes = des réponses API obsolètes. Consultez le guide des indexeurs pour la maintenance.


GraphQL vs REST : quand utiliser quoi

Cas d’utilisationAPI recommandée
Vitrine / PWA / application mobileGraphQL
Intégrations admin (commandes, import catalogue)REST (Async Bulk API)
Synchronisation ERP tierceREST
Panier/checkout en temps réelGraphQL
Intégrations legacyREST

La direction d’Adobe est claire : GraphQL pour le face-client, REST pour les opérations groupées opérationnelles/back-office.


FAQ technique

Où est défini le schéma GraphQL ?

Les fichiers de schéma de base vivent dans etc/schema.graphqls de chaque module. Magento les fusionne à l’exécution. Les modules personnalisés ajoutent leur propre etc/schema.graphqls.

Puis-je utiliser GraphQL dans l’Admin ?

GraphQL est conçu pour les opérations de vitrine. Les fonctionnalités Admin utilisent REST ou l’interface Admin — n’exposez pas les opérations Admin via GraphQL personnalisé sans contrôles ACL stricts.

Comment déboguer les erreurs GraphQL ?

Activez le mode développeur et vérifiez var/log/exception.log. GraphQL renvoie les erreurs dans le tableau errors de la réponse JSON avec les champs message et category.

GraphQL remplace-t-il le checkout Knockout.js ?

Pas automatiquement. Le checkout Luma est toujours basé sur Knockout. Le checkout headless nécessite un frontend qui consomme les mutations GraphQL (React, Vue, Hyvä Checkout, etc.). Consultez le guide checkout pour travailler avec Knockout.js ou construire une alternative headless.

GraphQL est-il disponible dans Magento Open Source ?

Oui. GraphQL fait partie de Magento Open Source depuis 2.3.x. Certaines fonctionnalités avancées (limites de complexité des requêtes, aperçus de staging) sont réservées à Adobe Commerce.


Conclusion

GraphQL est la couche API standard pour les vitrines Magento 2 modernes. Maîtrisez d’abord le schéma intégré des produits et du panier, puis étendez-le avec des résolveurs personnalisés lorsque la logique métier l’exige. Gardez les requêtes légères, les indexeurs à jour et les tokens d’authentification frais — et votre vitrine headless restera rapide et fiable.

Vous construisez une vitrine headless Magento 2 ou avez besoin d’endpoints GraphQL personnalisés ? Contactez-moi pour des revues d’architecture, des modules personnalisés et de l’optimisation des performances.