Type Definitions
A TypeDefinition is one unit of GraphQL schema. It provides an SDL string that declares your types, and a resolver
map that tells the engine which FieldResolver to call for fields with custom logic.
The Interface
interface TypeDefinition
{
public function getSdl(): string;
public function getResolvers(): array;
}
getSdl() returns a GraphQL SDL string. It may define new object types and extend the root Query or Mutation types
to add fields:
type Book { id: ID! title: String! }
extend type Query { books: [Book!]! book(id: ID!): Book }
getResolvers() returns a nested array keyed by type name → field name → FieldResolver class-string. Only fields
with custom logic need entries; all other fields fall through to default property resolution.
public function getResolvers(): array
{
return [
'Query' => [
'books' => BooksResolver::class,
'book' => BookByIdResolver::class,
],
];
}
Complete Example
<?php
use PHPNomad\GraphQL\Interfaces\TypeDefinition;
final class BookTypeDefinition implements TypeDefinition
{
public function getSdl(): string
{
return <<<'SDL'
type Book {
id: ID!
title: String!
}
extend type Query {
books: [Book!]!
book(id: ID!): Book
}
SDL;
}
public function getResolvers(): array
{
return [
'Query' => [
'books' => BooksResolver::class,
'book' => BookByIdResolver::class,
],
];
}
}
SDL Conventions
The execution engine (e.g. WebonyxGraphQLStrategy) pre-seeds the schema with base Query and Mutation types.
Your type definitions should extend them rather than re-define them:
# Correct — extend the base Query type
extend type Query { books: [Book!]! }
# Wrong — do not re-declare Query or Mutation
type Query { books: [Book!]! }
You can declare as many object types as needed in a single getSdl() return value.
Default Property Resolution
For object fields not listed in getResolvers(), the engine falls back to default resolution:
- If
$rootValueis an array, it reads$rootValue['fieldName']. - If
$rootValueis an object, it reads$rootValue->fieldName(or calls the getter if__getis defined).
This means you only need to write a FieldResolver when the default resolution is not sufficient — for example, when
deriving a value from multiple sources or calling a service.
Registering Type Definitions
Register your TypeDefinition classes through an
initializer implementing HasTypeDefinitions.
The bootstrapper will pass each definition into the active GraphQLStrategy during application boot.