bnnvara/graphql-bundle

GraphQL package for BNNVARA


License
MIT

Documentation

README

Build Status Code Coverage Scrutinizer Code Quality

##Installation

Using Composer:

composer require bnnvara/graphql-bundle

Enable the bundle in bundles.php.

return [
    ...
    BNNVARA\GraphQLBundle\BNNVARAGraphQLBundle::class => ['all' => true],
    ...
];

Query

This document does not explain the inner workings of graphql. There are great resources available online to get familiair with graphql.

In this example we use the following Query:

public function __construct()
{
    $config = [
        'name' => 'Query',
        'fields' => [
            'user' => [
                'type' => Types::user(),
                'description' => 'Returns user by id (in range of 1-5)',
                'args' => [
                    'id' => Types::nonNull(Types::id())
                ]
            ],
            'viewer' => [
                'type' => Types::user(),
                'description' => 'Represents currently logged-in user (for the sake of example - simply returns user with id == 1)'
            ]
        ],
        'resolveField' => function($val, $args, $context, ResolveInfo $info) {
            return $this->{$info->fieldName}($val, $args, $context, $info);
        }
    ];
    parent::__construct($config);
}

public function user($rootValue, $args)
{
    return DataSource::findUser($args['id']);
}

public function viewer($rootValue, $args, AppContext $context)
{
    return $context->viewer;
}

To create a Query like this using the BNNVARA\GraphQLBundle you need to create to classes. Each implementing an interface:

  • QueryInterface
  • ResolverInterface

The implementation of the QueryInterface looks as follows:

namespace Example\NameSpace;

class UserQuery implements QueryInterface
{
    public function __construct(ResolverInterface $resolver)
    {
        $this->resolver = $resolver;
    }

    public function getName(): string
    {
        return 'user';
    }

    public function getQuery(): array
    {
        return [
            'type' => Types::user(),
            'description' => 'Returns user by id (in range of 1-5)',
            'args' => [
                'id' => Types::nonNull(Types::id())
            ]
        ];
    }

    public function getResolver(): ResolverInterface
    {
        return $this->resolver;
    }
}

The implementation of the ResolverInterface looks as folows:

namespace Example\NameSpace;

class UserResolver implements ResolverInterface
{
    public function resolve($val, $args, $context, ResolveInfo $info)
    {
        return DataSource::findUser($args['id']);
    }

    public function isSupported($val, $args, $context, ResolveInfo $info): bool
    {
        return $info->fieldName === 'user';
    }
}

The last step to make a Query work is tagging the UserQuery service:

Example\NameSpace\UserQuery:
    tags: ['bnnvara.graph_ql.query']

The bundle takes care of the rest

Mutation

In progress

##Logger

The BNNVARA/GraphQLBundle implements the PSR\LoggerInterface. So it is possible to configure your own prefered logger. By default the NullLogger included in de PSR\Log package is used. You can change the logger to, for example, the monolog logger by creating config/packages/bnnvara_graphql.yaml and add the following lines, where monolog.logger is the name of the service you want to use:

bnnvara_graphql:
    logger_service: monolog.logger

##Cache

IMPORTANT Only use caching for anonymous queries. All executed queries are cached, so if one of the query is not anonymous don't use this feature

Caching is disabled by default, but can be enabled easily. Doctrine/Cache is used as caching provider but not installed because caching is disabled by default. Doctrine cache can be installed with the following command:

composer require doctrine/doctrine-cache-bundle

The cache bundle is used to ease setting up the cache driver. To define a redis driver just create app/config/packages/doctrine_cache.yaml and add the following lines (don't forget to define the used variables):

doctrine_cache:
    providers:
        response_cache:
            type: redis
            redis:
                host: "%env(REDIS_HOST)%"
                port: "%env(REDIS_PORT)%"

Now the container contains a service with the name doctrine_cache.providers.response_cache. Next step is to add configuration for the cache:

bnnvara_graphql:
    cache:
        caching_driver: "%env(GRAPHQL_CACHING_DRIVER)%"
        lifetime: "%env(GRAPHQL_CACHE_LIFETIME)%"

Now all succesful request will be cached. Enjoy!