Internals
Mapping types
The core of GraphQLite is its ability to map PHP types to GraphQL types. This mapping is performed by a series of "type mappers".
GraphQLite contains 4 categories of type mappers:
- Parameter mappers
- Root type mappers
- Recursive (class) type mappers
- (class) type mappers
Root type mappers
(Classes implementing the RootTypeMapperInterface
)
These type mappers are the first type mappers called.
They are responsible for:
- mapping scalar types (for instance mapping the "int" PHP type to GraphQL Integer type)
- detecting nullable/non-nullable types (for instance interpreting "?int" or "int|null")
- mapping list types (mapping a PHP array to a GraphQL list)
- mapping union types
- mapping enums
Root type mappers have access to the context of a type: they can access the PHP DocBlock and read annotations. If you want to write a custom type mapper that needs access to annotations, it needs to be a "root type mapper".
GraphQLite provides 6 classes implementing RootTypeMapperInterface
:
NullableTypeMapperAdapter
: a type mapper in charge of making GraphQL types non-nullable if the PHP type is non-nullableIteratorTypeMapper
: a type mapper in charge of iterable types (for instance:MyIterator|User[]
)CompoundTypeMapper
: a type mapper in charge of union typesMyCLabsEnumTypeMapper
: maps MyCLabs/enum types to GraphQL enum types (Deprecated: use native enums)EnumTypeMapper
: maps PHP enums to GraphQL enum typesBaseTypeMapper
: maps scalar types and lists. Passes the control to the "recursive type mappers" if an object is encountered.FinalRootTypeMapper
: the last type mapper of the chain, used to throw error if no other type mapper managed to handle the type.
Type mappers are organized in a chain; each type-mapper is responsible for calling the next type mapper.
Class type mappers
(Classes implementing the TypeMapperInterface
)
Class type mappers are mapping PHP classes to GraphQL object types.
GraphQLite provide 3 default implementations:
CompositeTypeMapper
: a type mapper that delegates mapping to other type mappers using the Composite Design Pattern.GlobTypeMapper
: scans classes in a directory for the#[Type]
or#[ExtendType]
attribute and maps those to GraphQL typesPorpaginasTypeMapper
: maps and class implementing the PorpaginasResult
interface to a special paginated type.
Registering a type mapper in Symfony
If you are using the GraphQLite Symfony bundle, you can register a type mapper by tagging the service with the "graphql.type_mapper" tag.
Registering a type mapper using the SchemaFactory
If you are using the SchemaFactory
to bootstrap GraphQLite, you can register a type mapper using the SchemaFactory::addTypeMapper
method.
Recursive type mappers
(Classes implementing the RecursiveTypeMapperInterface
)
There is only one implementation of the RecursiveTypeMapperInterface
: the RecursiveTypeMapper
.
Standard "class type mappers" are mapping a given PHP class to a GraphQL type. But they do not handle class hierarchies. This is the role of the "recursive type mapper".
Imagine that class "B" extends class "A" and class "A" maps to GraphQL type "AType".
Since "B" is a "A", the "recursive type mapper" role is to make sure that "B" will also map to GraphQL type "AType".
Parameter mapper middlewares
"Parameter middlewares" are used to decide what argument should be injected into a parameter.
Let's have a look at a simple query:
/**
* @return Product[]
*/
#[Query]
public function products(ResolveInfo $info): array
As you may know, the ResolveInfo
object injected in this query comes from Webonyx/GraphQL-PHP library.
GraphQLite knows that is must inject a ResolveInfo
instance because it comes with a ResolveInfoParameterHandler
class
that implements the ParameterMiddlewareInterface
).
You can register your own parameter middlewares using the SchemaFactory::addParameterMiddleware()
method, or by tagging the
service as "graphql.parameter_middleware" if you are using the Symfony bundle.