Ein Schema mit graphql-php erstellen
Typen und ein Schema mit webonyx/graphql-php definieren
Ein Schema mit graphql-php erstellen ist eine kostenlose PHP Academy-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des PHP Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der PHP Academy-Kurs umfasst insgesamt 4 Lektionen.
graphql-php: Die Referenzimplementierung
webonyx/graphql-php ist die De-facto-PHP-Portierung der GraphQL-Referenzimplementierung. Sie liefert Ihnen Typsystem, Parser, Validator und Executor. Sie definieren Ihr Schema entweder programmatisch (PHP-Objekte) oder aus SDL (schema-first). In dieser Lektion erstellen wir ein Schema von Hand, damit Sie genau verstehen, was die einzelnen Bestandteile tun.
composer require webonyx/graphql-phpSkalare und die Typ-Registry
Jeder GraphQL-Wert läuft letztlich auf einen Skalar hinaus: Int, Float, String, Boolean, ID. In graphql-php liegen diese auf der Type-Fassade. Da Objekttypen aufeinander (und auf sich selbst) verweisen, ist eine statische TypeRegistry ein gängiges Muster, die jeden Typ zwischenspeichert, sodass Sie ihn nur einmal erstellen.
<?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!"
Einen ObjectType definieren
Ein ObjectType hat einen name und eine fields-Map. Jedes Feld legt seinen type fest und kann optional einen resolve-Callback deklarieren. Wenn Sie resolve weglassen, verwendet graphql-php den Standard-Resolver, der den passenden Array-Schlüssel oder die Eigenschaft bzw. den Getter aus dem Parent-Wert liest.
<?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(),
],
]);
Non-Null- und Listen-Typen
Wrapping-Typen drücken Nullbarkeit und Kardinalität aus:
Type::nonNull(T)→T!(nie null).Type::listOf(T)→[T](eine Liste, möglicherweise null und möglicherweise mit null-Elementen).[Post!]!= eine Non-Null-Liste aus Non-Null-Posts →nonNull(listOf(nonNull($postType))).
Behalten Sie dies im Hinterkopf: Es ist der Nullbarkeitsvertrag Ihres Schemas mit den 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!]!
Lazy Fields durchbrechen zirkuläre Referenzen
Ein User hat posts, und ein Post hat einen author (einen User). Um Typen aufzubauen, die gegenseitig aufeinander verweisen, übergeben Sie fields als Closure statt als Array. Die Closure wird verzögert ausgeführt, nachdem beide Typen existieren, und umgeht so das Henne-Ei-Problem.
<?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
],
]);
}
}
Feldargumente
Felder können Argumente entgegennehmen. Deklarieren Sie sie unter dem Schlüssel args; sie treffen als zweiter Parameter ($args) des Resolvers ein. Argumente sind selbst typisiert, können Non-Null sein und defaultValue enthalten.
<?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']})",
];
Der Root-Query-Typ
Jedes Schema benötigt einen Root-Typ Query — die Einstiegspunkte, an denen Clients ihre Abfragen beginnen können. Hier stellen wir ein einzelnes hello-Feld bereit, damit wir die Ausführung durchgängig testen können. Das erste Argument des Root-Resolvers ist der rootValue des Schemas (häufig 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'],
],
],
]);
Schema zusammenbauen und ausführen
Verpacken Sie den Query-Typ in ein Schema und führen Sie einen Query-String über GraphQL::executeQuery() aus. Das Ergebnisobjekt wird über toArray() in das kanonische Array { data, errors } umgewandelt.
<?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"}}
Schema-first-Alternative mit BuildSchema
Wenn Sie SDL bevorzugen, analysiert BuildSchema::build() einen Schema-String und erstellt daraus ein ausführbares Schema. Anschließend binden Sie Resolver separat an (z. B. über einen Field-Resolver-Callback). So bleiben die Typdefinitionen deklarativ, während die Logik in PHP verbleibt.
<?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.
Vor dem Deployment validieren
graphql-php validiert eingehende Abfragen vor der Ausführung automatisch anhand des Schemas. Sie können außerdem zur Build-/CI-Zeit mit $schema->assertValid() prüfen, dass das Schema selbst intern konsistent ist — so erkennen Sie Tippfehler und fehlerhafte Verweise vor dem Deployment und nicht erst zum Zeitpunkt der Anfrage.
<?php
use GraphQL\Type\Schema;
/** @var Schema $schema */
$schema->assertValid(); // throws InvariantViolation on a broken schema
echo "schema OK\n";
Enums und benutzerdefinierte Skalare
Neben Objekten ergänzen zwei weitere Typarten die meisten Schemas. EnumType beschränkt ein Feld auf eine feste Menge benannter Werte. Mit CustomScalarType können Sie Domänen-Skalare (DateTime, Email) mit eigener serialize/parseValue/parseLiteral-Logik definieren, sodass Werte an der Grenze validiert und normalisiert werden.
<?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.
Wissenscheck
Warum übergeben Sie fields als Closure?
Zusammenfassung
Sie haben ein Schema von Grund auf aufgebaut:
- Skalare und Wrapping-Typen (
nonNull,listOf) drücken den Vertrag für Nullbarkeit und Kardinalität aus. ObjectTypemit einer Fields-Map (oder Lazy-Closure) definiert Ihre Strukturen.- Eine zwischenspeichernde Typ-Registry verarbeitet zirkuläre Referenzen.
- Felder akzeptieren typisierte
args; der Root-TypQueryist der Einstiegspunkt. GraphQL::executeQuery()führt es aus;assertValid()schützt das Schema in der CI.
Als Nächstes: Resolver, Mutations und Subscriptions.
Häufig gestellte Fragen
Ist die Lektion „Ein Schema mit graphql-php erstellen“ kostenlos?
Ja — der vollständige Text von „Ein Schema mit graphql-php erstellen“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des PHP Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der PHP Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Ein Schema mit graphql-php erstellen“?
Typen und ein Schema mit webonyx/graphql-php definieren Du übst PHP Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um PHP Academy zu starten?
Keine Vorkenntnisse erforderlich. PHP Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.
Wie lange dauert die Lektion „Ein Schema mit graphql-php erstellen“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser PHP Academy-Lektion Code schreiben und ausführen?
Ja. Jede PHP Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- GraphQL vs. REST
- Ein Schema mit graphql-php erstellen
- Resolver, Mutationen und Subscriptions
- Performance: N+1 und DataLoader