1. Go to this page and download the library: Download le0daniel/graphql-tools library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
le0daniel / graphql-tools example snippets
use GraphQlTools\Helper\Registry\SchemaRegistry;
use GraphQlTools\Contract\TypeRegistry;
use GraphQlTools\Definition\Field\Field;
use GraphQlTools\Helper\QueryExecutor;
use GraphQlTools\Definition\Extending\Extend;
ypes
$schemaRegistry->register(Type::class);
// You can extend types and interfaces with additional fields
// See: Extending Types
$schemaRegistry->extend(
Extend::type('Lion')->withFields(fn(TypeRegistry $registry) => [
Field::withName('species')->ofType($registry->string())
])
);
$schema = $schemaRegistry->createSchema(
RootQueryType::class, // Define
'MutationRoot', // Your own root mutation type,
);
$executor = new QueryExecutor();
$result = $executor->execute(
$schema,
' query { whoami }',
new Context(),
[], // variables array
null, // Root Value
null, // operation name
);
use GraphQlTools\Helper\Registry\SchemaRegistry;
use GraphQlTools\Utility\TypeMap;
$schemaRegistry = new SchemaRegistry();
[$types, $typeExtensions] = TypeMap::createTypeMapFromDirectory('/your/directory/with/GraphQL');
$schemaRegistry->registerTypes($types);
$schemaRegistry->extendMany($typeExtensions);
use GraphQlTools\Helper\Registry\SchemaRegistry;
use GraphQlTools\Utility\TypeMap;
$schemaRegistry = new SchemaRegistry();
$schemaRegistry->register(SomeName\Space\MyType::class);
// You can now use both, the class name or the type name as in GraphQL.
$registry->type(SomeName\Space\MyType::class) === $registry->type('My');
use GraphQlTools\Helper\Registry\SchemaRegistry;
use GraphQlTools\Helper\Registry\TagBasedSchemaRules;
use GraphQlTools\Contract\SchemaRules;
$schemaRegistry = new SchemaRegistry();
// Register all kind of types
$publicSchema = $schemaRegistry->createSchema(
queryTypeName: 'Query',
schemaRules: new TagBasedSchemaRules(ignoreWithTags: 'unstable', onlyWithTags: 'public')
);
$publicSchemaWithUnstableFields = $schemaRegistry->createSchema(
queryTypeName: 'Query',
schemaRules: new TagBasedSchemaRules(onlyWithTags: 'public')
);
class MyCustomRule implements SchemaRules {
public function isVisible(Field|InputField|EnumValue $item): bool {
// Determine if a field is visible or not.
return Arr::contains('my-tag', $item->getTags());
}
}
use GraphQlTools\Definition\GraphQlType;
use GraphQlTools\Contract\TypeRegistry;
use GraphQlTools\Definition\Field\Field;
use GraphQL\Type\Definition\NonNull;
class QueryType extends GraphQlType {
// Define Fields of the type. Use the type registry to reference all other types in the schema.
// You MUST use the type registry for referencing all types. The type registry guarantees that the type is only
// created once and reused everywhere.
protected function fields(TypeRegistry $registry) : array {
return [
Field::withName('currentUser')
->ofType(new NonNull($registry->string()))
->resolvedBy(fn(array $user) => $user['name']),
// More fields
];
}
protected function description() : string{
return 'Entry point into the schema query.';
}
// Optional
protected function interfaces(): array {
return [
UserInterface::class,
'Animal',
];
}
// Optional, define middlewares for the resolver. See Middlewares.
protected function middleware() : array|null{
return [];
}
}
use GraphQlTools\Definition\Field\Field;
use GraphQL\Type\Definition\NonNull;
use GraphQL\Type\Definition\ListOfType;
/** @var \GraphQlTools\Contract\TypeRegistry $registry */
// In type Animal
Field::withName('myField')->ofType(new NonNull($registry->id()));
Field::withName('myOtherField')->ofType(new ListOfType($registry->type('Other')));
// Results in GraphQL
// type Animal {
// myField: String!
// myOtherField: [Other]
// }
use GraphQlTools\Definition\GraphQlType;
use GraphQlTools\Contract\TypeRegistry;
use GraphQlTools\Definition\Field\Field;
use GraphQL\Type\Definition\ResolveInfo;
use GraphQL\Type\Definition\NonNull;
final class AnimalType extends GraphQlType {
// ...
protected function fields(TypeRegistry $registry) : array {
return [
// Uses the default resolver
Field::withName('id')->ofType($registry->id()),
// Define custom types using the repository
Field::withName('customType')
->withDescription('This is a custom type')
->ofType($registry->type(CustomType::class))
->tags('public', 'stable'),
// Using type name instead of class name
Field::withName('customType2')
->ofType($registry->type('Custom'))
->tags('public', 'stable'),
// With Resolver
Field::withName('userName')
->ofType($registry->string())
->resolvedBy(fn(User $user, array $arguments, $context, ResolveInfo $info): string => $user->name),
// Define arguments
Field::withName('fieldWithArgs')
->ofType($registry->string())
->withArguments(
// Define named arguments, works for all fields
InputField::withName('name')
->ofType(new NonNull($registry->string()))
->withDefaultValue('Anonymous')
->withDescription('My Description')
)
->resolvedBy(function ($data, array $arguments, $context, ResolveInfo $resolveInfo): string {
return "Hello {$arguments['name']}";
})
];
}
}
use GraphQlTools\Definition\Field\Field;
use GraphQlTools\Contract\TypeRegistry;
use GraphQlTools\Definition\GraphQlType;
use GraphQL\Type\Definition\NonNull;
class ReusableFields {
public static function id(): Field {
return Field::withName('id')
->ofTypeResolver(fn(TypeRegistry $registry) => new NonNull($registry->id()))
->withDescription('Globally unique identifier.')
->resolvedBy(fn(Identifiable $data): string => $data->globallyUniqueId());
}
}
// Usage in type:
class MyType extends GraphQlType {
protected function fields(TypeRegistry $registry) : array {
return [
ReusableFields::id()
->name('id')
->withDescription('Overwritten description...'),
// Other Fields
Field::withName('other')->ofType($registry->string()),
];
}
}
$field->cost(2, fn(array $args): int => $args['first'] ?? 15);
use GraphQL\Type\Definition\ResolveInfo;
use Closure;
$middleware = function(mixed $data, array $arguments, $context, ResolveInfo $resolveInfo, Closure $next): mixed {
// Do something before actually resolving the field.
if (!$context->isAdmin()) {
return null;
}
$result = $next($data, $arguments, $context, $resolveInfo);
// Do something after the field was resolved. You can manipulate the result here.
if ($result === 'super secret value') {
return null;
}
return $result;
}
use GraphQlTools\Helper\Registry\SchemaRegistry;
use GraphQlTools\Contract\TypeRegistry;
use GraphQlTools\Definition\Field\Field;
use GraphQlTools\Definition\Extending\Extend;
$schemaRegistry = new SchemaRegistry();
$schemaRegistry->extend(
Extend::type('Animal')->withFields(fn(TypeRegistry $registry): array => [
Field::withName('family')
->ofType($registry->string())
->resolvedBy(fn() => 'Animal Family')
]),
);
use GraphQlTools\Definition\Extending\ExtendGraphQlType;
use GraphQlTools\Contract\TypeRegistry;
use GraphQlTools\Helper\Registry\SchemaRegistry;
class ExtendsAnimalType extends ExtendGraphQlType {
public function fields(TypeRegistry $registry) : array {
return [
Field::withName('family')
->ofType($registry->string())
->resolvedBy(fn() => 'Animal Family')
];
}
// Optional
protected function middleware() : array{
return [];
}
// Optional, can be inferred by class name
// Follow naming pattern: Extends[TypeOrInterfaceName][Type|Interface]
public function typeName(): string {
return 'Animal';
}
}
$schemaRegistry = new SchemaRegistry();
$schemaRegistry->extend(ExtendsAnimalType::class);
// If the class does not follow the naming patterns, you need to use the extended type name
$schemaRegistry->extend(ExtendsAnimalType::class, 'Animal');
// OR
$schemaRegistry->extend(new ExtendsAnimalType());
use GraphQlTools\Definition\Field\Field;
use GraphQlTools\Utility\Middleware\Federation;
use GraphQlTools\Contract\TypeRegistry;
/** @var TypeRegistry $registry */
Field::withName('extendedField')
->ofType($registry->string())
->middleware(Federation::key('id'))
->resolvedBy(fn(string $animalId) => "Only the ID is received, not the complete Animal Data.");
use GraphQlTools\Helper\QueryExecutor;
use GraphQlTools\Helper\Validation\QueryComplexityWithExtension;
use GraphQlTools\Helper\Validation\CollectDeprecatedFieldNotices;
$executor = new QueryExecutor(
[fn($context) => new YourTelemetryExtension],
[CollectDeprecatedFieldNotices::class, fn($context) => new QueryComplexityWithExtension($context->maxAllowedComplexity)],
function(Throwable $throwable, \GraphQL\Error\Error $error): void {
YourLogger::error($throwable);
},
function(Throwable $throwable): Throwable {
match ($throwable::class) {
AuthenticationError::class => GraphQlErrorWhichIsClientAware($throwable),
default => $throwable
}
}
);
$result = $executor->execute(/* ... */);
// You can access extensions after the execution
$telemetryExtension = $result->getExtension(YourTelemetryExtension::class);
$application->storeTrace($telemetryExtension->getTrace());
// You can access validation rules after execution
$deprecationNotices = $result->getValidationRule(CollectDeprecatedFieldNotices::class);
$application->logDeprecatedUsages($deprecationNotices->getMessages());
$jsonResult = json_encode($result);
use GraphQlTools\Helper\QueryExecutor;
use GraphQlTools\Helper\Validation\ValidateDeferUsageOnFields;
use GraphQlTools\Helper\Extension\DeferExtension;
use GraphQlTools\Helper\Results\CompleteResult;
use GraphQlTools\Helper\Results\PartialResult;
use GraphQlTools\Helper\Results\PartialBatch;
$executor = new QueryExecutor(
[fn() => new DeferExtension()],
[new ValidateDeferUsageOnFields(10)]
);
$generator = $executor->executeGenerator(/* ... */);
/** @var CompleteResult|PartialResult $initialResult */
$initialResult = $generator->current();
/* SEND INITIAL RESPONSE */
$generator->next();
while ($result = $generator->current()) {
$generator->next();
/** @var PartialResult|PartialBatch $result */
/* Send next chunk */
}
/* Close Response */
use GraphQlTools\Helper\Extension\Extension;
use GraphQlTools\Utility\Time;
use GraphQlTools\Data\ValueObjects\Events\FieldResolution;
class MyCustomExtension extends Extension {
//...
public function visitField(FieldResolution $event) : ?Closure{
Log::debug('Will resolve field', ['name' => $event->info->fieldName, 'typeData' => $event->typeData, 'args' => $event->arguments]);
return fn($resolvedValue) => Log::debug('did resolve field value to', [
'value' => $resolvedValue,
'durationNs' => Time::durationNs($event->eventTimeInNanoSeconds),
]);
}
}
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.