Split up schema
It is possible to split up the schema into MODULENAME.gql files that live in Drupal module folders.
You need to use SdlModuleSchemaPluginBase
, for example like this:
<?php
namespace Drupal\example\Plugin\GraphQL\Schema;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\graphql\GraphQL\Execution\ResolveContext;
use Drupal\graphql\GraphQL\ResolverRegistry;
use Drupal\graphql\Plugin\GraphQL\Schema\SdlModuleSchemaPluginBase;
use Drupal\graphql\Plugin\ResolverMapPluginManager;
use GraphQL\Type\Definition\ResolveInfo;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Example GraphQL schema.
*
* @Schema(
* id = "example",
* name = "Example schema"
* )
*/
class SdlSchemaExample extends SdlModuleSchemaPluginBase {
/**
* GraphQL resolver registry map manager.
*
* @var \Drupal\graphql\Plugin\ResolverMapPluginManager
*/
protected $registryMapManager;
/**
* {@inheritdoc}
*/
public function __construct(array $configuration, string $plugin_id, array $plugin_definition, CacheBackendInterface $astCache, $config, ModuleHandlerInterface $module_handler, ResolverMapPluginManager $registry_map_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $astCache, $config, $module_handler);
$this->registryMapManager = $registry_map_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('cache.graphql.ast'),
$container->getParameter('graphql.config'),
$container->get('module_handler'),
$container->get('plugin.manager.graphql.resolver_map')
);
}
/**
* {@inheritdoc}
*/
protected function getResolverRegistry() {
$registry = new ResolverRegistry([], [
__CLASS__,
'defaultFieldResolver',
]);
return $this->registryMapManager->registerResolvers($this->getPluginId(), $registry);
}
/**
* The default field resolver.
*
* Used if no field resolver was explicitly registered.
*
* @param mixed $source
* The source (parent) value.
* @param array $args
* An array of arguments.
* @param \Drupal\graphql\GraphQL\Execution\ResolveContext $context
* The context object.
* @param \GraphQL\Type\Definition\ResolveInfo $info
* The resolve info object.
*
* @return mixed
* The result for the field.
*/
public static function defaultFieldResolver($source, array $args, ResolveContext $context, ResolveInfo $info) {
$fieldName = $info->fieldName;
$property = NULL;
if (is_array($source) || $source instanceof \ArrayAccess) {
if (isset($source[$fieldName])) {
$property = $source[$fieldName];
}
}
else {
if (is_object($source) && isset($source->{$fieldName})) {
$property = $source->{$fieldName};
}
// Allow methods on wrapper objects with the same name to be used as
// callbacks to resolve the field value.
else {
if (is_callable([$source, $fieldName])) {
$property = [$source, $fieldName];
}
}
}
if (is_callable($property)) {
return $property($source, $args, $context, $info);
}
return $property;
}
}
Then you can specify your graphql schema in a MODULENAME.gql file:
schema {
query: Query
}
type Query {
article(id: Int!): Article
page(id: Int!): Page
node(id: Int!): NodeInterface
label(id: Int!): String
}
type Article implements NodeInterface {
id: Int!
uid: String
title: String!
render: String
}
type Page implements NodeInterface {
id: Int!
uid: String
title: String
}
interface NodeInterface {
id: Int!
}
And the resolver mapping in an @ResolverMap
plugin:
<?php
namespace Drupal\example\Plugin\GraphQL\ResolverMap;
use Drupal\Core\Plugin\PluginBase;
use Drupal\graphql\GraphQL\ResolverBuilder;
use Drupal\graphql\GraphQL\ResolverRegistry;
use Drupal\graphql\Plugin\ResolverMapPluginInterface;
/**
* Registers common field/type resolvers.
*
* @ResolverMap(
* id = "example_common_resolvers",
* schema = "example",
* )
*/
class CommonResolvers extends PluginBase implements ResolverMapPluginInterface {
/**
* {@inheritdoc}
*/
public function registerResolvers(ResolverRegistry $registry, ResolverBuilder $builder) {
$registry->addFieldResolver('Query', 'node',
$builder->produce('entity_load', ['mapping' => [
'entity_type' => $builder->fromValue('node'),
'entity_id' => $builder->fromArgument('id'),
]])
);
$registry->addFieldResolver('Query', 'label',
$builder->produce('entity_label', ['mapping' => [
'entity' => $builder->produce('entity_load', ['mapping' => [
'entity_type' => $builder->fromValue('node'),
'entity_bundle' => $builder->fromValue(['article']),
'entity_id' => $builder->fromArgument('id'),
]])
]])
);
// ... Add more field resolvers here.
}
}
A module can also extend the schema of another module with MODULENAME.extend.gql:
extend type Query {
resumeByUserId(userId: Int): ContentResponse
}
extend type Mutation {
updateResume(id: Int, data: ResumeInput): ContentResponse
}
extend union Content = Resume
The field resolvers for the schema extension are added with the others in @ResolverMap
plugins.
Last updated