Sometimes you have a niche scenario that requires some custom code to resolve. Either because using some contrib module that has no direct GraphQL support, or its just a very custom coded part that needs some massaging in order to get the exact data you want.
Custom data producers allow you essentially hook into any data of Drupal, because its a class and you can use services, request any kind of data.
Lets look at a custom Data producer that loads the current user (similar to the 3.x version of currentUser query).
The first step as seen before is to add our query to the schema :
type Query {
...
currentUser: User
...
}
type User {
id: Int
name: String
}
Now that we have this we need to make a resolver that actually loads this user, but for that first we need our own custom data producer "CurrentUser" :
<?phpnamespaceDrupal\example\Plugin\GraphQL\DataProducer;useDrupal\Core\Plugin\ContainerFactoryPluginInterface;useDrupal\Core\Session\AccountInterface;useDrupal\graphql\Plugin\GraphQL\DataProducer\DataProducerPluginBase;useSymfony\Component\DependencyInjection\ContainerInterface;/** * Gets the ID of current user. * * @DataProducer( * id = "current_user", * name = @Translation("Current user"), * description = @Translation("Current logged in user."), * produces = @ContextDefinition("any", * label = @Translation("Current user") * ) * ) */classCurrentUserextendsDataProducerPluginBaseimplementsContainerFactoryPluginInterface {/** * The current user. * * @var\Drupal\Core\Session\AccountInterface */protected $currentUser;/** * {@inheritdoc} */publicstaticfunctioncreate(ContainerInterface $container,array $configuration, $plugin_id, $plugin_definition) {returnnewstatic( $configuration, $plugin_id, $plugin_definition, $container->get('current_user') ); }/** * UserRegister constructor. * * @paramarray $configuration * A configuration array containing information about the plugin instance. * @paramstring $plugin_id * The plugin_id for the plugin instance. * @paramarray $plugin_definition * The plugin implementation definition. * @param\Drupal\Core\Session\AccountInterface $current_user * The current user. */ public function __construct(array $configuration, string $plugin_id, array $plugin_definition, AccountInterface $current_user) {
parent::__construct($configuration, $plugin_id, $plugin_definition);$this->currentUser = $current_user; }/** * Returns current user id. * * @returnint * The current user id. */publicfunctionresolve() {return$this->currentUser->id(); }}
We are defining a custom data producer current_user that we can now use to resolve our query that we previously added to the schema. Notice that our data producer returns only the user id and not the actual user object. However we can combine it with an entity_load which is already made very efficient with in the module (taking advantage of caching strategies using buffering) so we don't have to actually load the user here.
Lets see how we can consume our newly created data producer :
Notice how we combine our custom data producer with a built-in entity_load to make querying more performance and standardized across. We will look at compose in more detail in the next section.