webonyx Integration
phpnomad/webonyx-integration is the concrete GraphQLStrategy implementation backed
by webonyx/graphql-php. It implements all the contracts defined in
phpnomad/graphql so you can drop it in without writing any engine code yourself.
Installation
composer require phpnomad/webonyx-integration
This pulls in webonyx/graphql-php ^15.0, phpnomad/graphql, and phpnomad/di automatically.
WebonyxGraphQLStrategy
PHPNomad\GraphQL\Webonyx\Strategies\WebonyxGraphQLStrategy implements GraphQLStrategy. Its constructor takes an
InstanceProvider (the DI container) and uses it to resolve FieldResolver classes at query time.
$strategy = new WebonyxGraphQLStrategy($container);
How schema building works
On first execute() call the strategy:
- Calls each registered
TypeDefinitiongetter to obtain a definition instance. - Starts with a base SDL that declares empty-safe
QueryandMutationroots. - Appends each definition's
getSdl(). - Merges all
getResolvers()maps into a single type → field → class-string table. - Calls
BuildSchema::build($fullSdl, $typeConfigDecorator)where the decorator attaches aresolveFieldclosure to any type with registered resolvers. - The
resolveFieldclosure resolves the resolver class from the container and callsresolve(). Fields with no entry fall back toExecutor::defaultFieldResolver.
The schema is cached after first build. Calling registerTypeDefinition() again invalidates the cache so the next
execute() rebuilds.
Binding the strategy
In an initializer, bind WebonyxGraphQLStrategy to the GraphQLStrategy interface:
<?php
use PHPNomad\GraphQL\Interfaces\GraphQLStrategy;
use PHPNomad\GraphQL\Webonyx\Strategies\WebonyxGraphQLStrategy;
final class GraphQLInitializer implements HasClassDefinitions
{
public function getClassDefinitions(): array
{
return [
WebonyxGraphQLStrategy::class => GraphQLStrategy::class,
];
}
}
Full bootstrap example
<?php
use PHPNomad\GraphQL\Interfaces\GraphQLStrategy;
use PHPNomad\GraphQL\Webonyx\Strategies\WebonyxGraphQLStrategy;
use PHPNomad\Di\Container;
// 1. Container
$container = new Container();
$container->bindSingleton(WebonyxGraphQLStrategy::class, GraphQLStrategy::class);
// 2. Strategy
$strategy = $container->get(GraphQLStrategy::class);
// 3. Register a type definition (normally done via HasTypeDefinitions initializer)
$strategy->registerTypeDefinition(fn() => new BookTypeDefinition());
// 4. Execute
$result = $strategy->execute('{ books { id title } }', [], $context);
echo json_encode($result);
// → {"data":{"books":[{"id":"1","title":"The Pragmatic Programmer"},{"id":"2","title":"Clean Code"}]}}
Implementing ResolverContext
WebonyxGraphQLStrategy passes the ResolverContext you supply directly to every FieldResolver::resolve() call as
the third argument. You implement it once to wrap your platform's request:
<?php
use PHPNomad\GraphQL\Interfaces\ResolverContext;
use PHPNomad\Http\Interfaces\Request;
final class HttpResolverContext implements ResolverContext
{
public function __construct(private readonly Request $request) {}
public function getRequest(): Request
{
return $this->request;
}
}