0Pricing
PHP Academy · Leçon

Créer un schéma avec graphql-php

Définissez des types et un schéma avec webonyx/graphql-php.

Créer un schéma avec graphql-php est une leçon PHP Academy gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage PHP Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours PHP Academy comprend 4 leçons au total.

graphql-php : l'implémentation de référence

webonyx/graphql-php est le port PHP de facto de l'implémentation de référence de GraphQL. Il fournit le système de types, l'analyseur, le validateur et l'exécuteur. Vous définissez votre schéma soit par programmation (objets PHP), soit à partir de SDL (approche schéma d'abord). Dans cette leçon, nous construisons un schéma à la main afin que vous compreniez exactement le rôle de chaque élément.

composer require webonyx/graphql-php

Scalaires et registre des types

Toute valeur GraphQL finit par être un scalaire : Int, Float, String, Boolean, ID. Dans graphql-php, ces types sont accessibles via la façade Type. Comme les types objet se référencent entre eux (et eux-mêmes), une pratique courante consiste à utiliser un TypeRegistry statique qui mémorise chaque type afin de ne le construire qu'une seule fois.

<?php
use GraphQL\Type\Definition\Type;

// Built-in scalars, returned as singletons:
var_dump(Type::int()->name);     // "Int"
var_dump(Type::string()->name);  // "String"
var_dump(Type::id()->name);      // "ID"
var_dump(Type::nonNull(Type::string())->toString()); // "String!"

Définir un ObjectType

Un ObjectType possède un name et une table fields. Chaque champ déclare son type et peut éventuellement fournir une fonction de rappel resolve. Si vous omettez resolve, graphql-php utilise le résolveur par défaut, qui lit la clé de tableau correspondante ou la propriété/l'accesseur de la valeur parente.

<?php
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;

$postType = new ObjectType([
    'name' => 'Post',
    'fields' => [
        'id'    => Type::nonNull(Type::id()),
        'title' => Type::nonNull(Type::string()),
        'body'  => Type::string(),
    ],
]);

Nullité et enveloppement par une liste

Les types enveloppants expriment la nullité et la cardinalité :

  • Type::nonNull(T) → T! (jamais nul).
  • Type::listOf(T) → [T] (une liste éventuellement nulle, pouvant contenir des membres nuls).
  • [Post!]! = une liste non nulle de publications non nulles → nonNull(listOf(nonNull($postType))).

Faites-le correctement : il s'agit du contrat de nullité de votre schéma avec les clients.

<?php
use GraphQL\Type\Definition\Type;

// [Post!]!  -- a required list whose elements are never null
$wrapped = Type::nonNull(Type::listOf(Type::nonNull(Type::string())));
echo $wrapped->toString(), "\n"; // [String!]!

Les champs différés brisent les références circulaires

Un User possède des posts, et un Post possède un author (un utilisateur). Pour construire des types qui se référencent mutuellement, transmettez fields sous forme de fermeture plutôt que de tableau. La fermeture s'exécute paresseusement une fois les deux types créés, ce qui évite le problème de la poule et de l'œuf.

<?php
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;

class Types {
    private static array $cache = [];

    public static function user(): ObjectType {
        return self::$cache['User'] ??= new ObjectType([
            'name' => 'User',
            'fields' => fn() => [           // lazy!
                'id'    => Type::nonNull(Type::id()),
                'name'  => Type::nonNull(Type::string()),
                'posts' => Type::listOf(self::post()),
            ],
        ]);
    }

    public static function post(): ObjectType {
        return self::$cache['Post'] ??= new ObjectType([
            'name' => 'Post',
            'fields' => fn() => [
                'id'     => Type::nonNull(Type::id()),
                'title'  => Type::nonNull(Type::string()),
                'author' => self::user(),    // back-reference
            ],
        ]);
    }
}

Arguments des champs

Les champs peuvent accepter des arguments. Déclarez-les sous la clé args ; ils arrivent comme deuxième paramètre ($args) du résolveur. Les arguments sont eux-mêmes typés, peuvent être non nuls et accepter une defaultValue.

<?php
use GraphQL\Type\Definition\Type;

$userField = [
    'type' => Type::string(),
    'args' => [
        'id'     => Type::nonNull(Type::id()),
        'locale' => ['type' => Type::string(), 'defaultValue' => 'en'],
    ],
    'resolve' => fn($root, array $args) => "user {$args['id']} ({$args['locale']})",
];

Le type Query racine

Chaque schéma a besoin d'un type Query racine : ce sont les points d'entrée à partir desquels les clients peuvent commencer. Ici, nous exposons un unique champ hello afin de pouvoir exécuter une requête de bout en bout. Le premier argument du résolveur racine est le rootValue du schéma (souvent null).

<?php
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;

$queryType = new ObjectType([
    'name' => 'Query',
    'fields' => [
        'hello' => [
            'type' => Type::string(),
            'args' => ['name' => Type::nonNull(Type::string())],
            'resolve' => fn($root, array $args) => 'Hello, ' . $args['name'],
        ],
    ],
]);

Assembler et exécuter le schéma

Enveloppez le type de requête dans un Schema et exécutez une chaîne de requête avec GraphQL::executeQuery(). L'objet de résultat est converti en tableau canonique { data, errors } au moyen de toArray().

<?php
require 'vendor/autoload.php';

use GraphQL\GraphQL;
use GraphQL\Type\Schema;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;

$queryType = new ObjectType([
    'name' => 'Query',
    'fields' => [
        'hello' => [
            'type' => Type::string(),
            'args' => ['name' => Type::nonNull(Type::string())],
            'resolve' => fn($root, $args) => 'Hello, ' . $args['name'],
        ],
    ],
]);

$schema = new Schema(['query' => $queryType]);
$result = GraphQL::executeQuery($schema, '{ hello(name: "Ada") }');
echo json_encode($result->toArray());
// {"data":{"hello":"Hello, Ada"}}

Alternative « schéma d'abord » avec BuildSchema

Si vous préférez SDL, BuildSchema::build() analyse une chaîne de schéma pour produire un schéma exécutable. Vous attachez ensuite les résolveurs séparément (par exemple, avec une fonction de rappel de résolution de champ), de sorte que les définitions de types restent déclaratives tandis que la logique demeure en PHP.

<?php
use GraphQL\Utils\BuildSchema;

$sdl = <<<'GQL'
type Query {
  hello(name: String!): String
}
GQL;

$schema = BuildSchema::build($sdl);
// Provide resolvers via the executeQuery $fieldResolver argument
// or with a type config decorator.

Validez avant la mise en production

graphql-php valide automatiquement les requêtes reçues par rapport au schéma avant leur exécution. Vous pouvez également vérifier que le schéma lui-même est cohérent au moment de sa construction ou dans l'intégration continue avec $schema->assertValid() — détectez les fautes de frappe et les références invalides avant le déploiement, et non au moment de la requête.

<?php
use GraphQL\Type\Schema;

/** @var Schema $schema */
$schema->assertValid(); // throws InvariantViolation on a broken schema
echo "schema OK\n";

Énumérations et scalaires personnalisés

Au-delà des objets, deux sortes de types complètent la plupart des schémas. EnumType contraint un champ à un ensemble fixe de valeurs nommées. CustomScalarType vous permet de définir des scalaires propres à votre domaine (DateTime, adresse e-mail) avec votre propre logique de serialize/parseValue/parseLiteral, afin que les valeurs soient validées et normalisées à la frontière.

<?php
use GraphQL\Type\Definition\EnumType;

$statusEnum = new EnumType([
    'name' => 'PostStatus',
    'values' => [
        'DRAFT'     => ['value' => 0],
        'PUBLISHED' => ['value' => 1],
        'ARCHIVED'  => ['value' => 2],
    ],
]);
// A field typed as $statusEnum only accepts DRAFT/PUBLISHED/ARCHIVED.

Vérification rapide

Pourquoi transmettre fields sous forme de fermeture ?

Récapitulatif

Vous avez construit un schéma à partir de zéro :

  • Les scalaires et les types enveloppants (nonNull, listOf) expriment le contrat de nullité et de cardinalité.
  • Un ObjectType avec une table de champs (ou une fermeture différée) définit vos structures.
  • Un registre de types avec mémorisation gère les références circulaires.
  • Les champs acceptent des args typés ; le type Query racine est le point d'entrée.
  • GraphQL::executeQuery() exécute le schéma ; assertValid() le protège dans l'intégration continue.

Ensuite : les résolveurs, les mutations et les souscriptions.

Questions Fréquemment Posées

La leçon « Créer un schéma avec graphql-php » est-elle gratuite ?

Oui — le texte complet de « Créer un schéma avec graphql-php » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours PHP Academy, passe à CoddyKit PRO. Le cours PHP Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Créer un schéma avec graphql-php » ?

Définissez des types et un schéma avec webonyx/graphql-php. Tu pratiques PHP Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer PHP Academy ?

Aucune expérience préalable n'est requise. PHP Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.

Combien de temps prend la leçon « Créer un schéma avec graphql-php » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon PHP Academy ?

Oui. Chaque leçon PHP Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. GraphQL ou REST
  2. Créer un schéma avec graphql-php
  3. Résolveurs, mutations et abonnements
  4. Performances : N+1 et DataLoader
← Retour à PHP Academy