Created
May 15, 2019 12:48
-
-
Save Jalle19/fc17e8046fa1d530c02c80c337e47e96 to your computer and use it in GitHub Desktop.
Example of advanced graphql-php usage
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Foo\Bar\GraphQL; | |
use Digia\GraphQL\Error\Handler\ErrorHandlerInterface; | |
use Digia\GraphQL\Error\InvariantException; | |
use Digia\GraphQL\Execution\ExecutionResult; | |
use Digia\GraphQL\Language\Node\DocumentNode; | |
use Digia\GraphQL\Language\ParserInterface; | |
use Digia\GraphQL\Language\Source; | |
use Digia\GraphQL\Language\SyntaxErrorException; | |
use Digia\GraphQL\Schema\Building\SchemaBuilderInterface; | |
use Digia\GraphQL\Schema\Resolver\ResolverRegistryInterface; | |
use Digia\GraphQL\Schema\Schema; | |
use Digia\GraphQL\Schema\Validation\SchemaValidationException; | |
use Illuminate\Contracts\Cache\Repository as CacheRepository; | |
use function Digia\GraphQL\execute; | |
use function Digia\GraphQL\parse; | |
use function Digia\GraphQL\validate; | |
use function Digia\GraphQL\validateSchema; | |
class GraphQLService | |
{ | |
private const SCHEMA_DOCUMENT_CACHE_KEY = 'graphql_schema_document'; | |
private const QUERY_VALIDATION_CACHE_KEY = 'graphql_query_validation'; | |
/** | |
* @var CacheRepository | |
*/ | |
private $cacheRepository; | |
/** | |
* @var SchemaBuilderInterface | |
*/ | |
private $schemaBuilder; | |
/** | |
* @var ParserInterface | |
*/ | |
private $parser; | |
/** | |
* @var ErrorHandlerInterface | |
*/ | |
private $errorHandler; | |
/** | |
* @var Source | |
*/ | |
private $schemaDefinition; | |
/** | |
* @var ResolverRegistryInterface | |
*/ | |
private $resolverRegistry; | |
/** | |
* @var array | |
*/ | |
private $options; | |
/** | |
* GraphQLService constructor. | |
* | |
* @param CacheRepository $cacheRepository | |
* @param SchemaBuilderInterface $schemaBuilder | |
* @param ParserInterface $parser | |
* @param ErrorHandlerInterface $errorHandler | |
* @param Source $schemaDefinition | |
* @param ResolverRegistryInterface $resolverRegistry | |
* @param array $options | |
*/ | |
public function __construct( | |
CacheRepository $cacheRepository, | |
SchemaBuilderInterface $schemaBuilder, | |
ParserInterface $parser, | |
ErrorHandlerInterface $errorHandler, | |
Source $schemaDefinition, | |
ResolverRegistryInterface $resolverRegistry, | |
array $options | |
) { | |
$this->cacheRepository = $cacheRepository; | |
$this->schemaDefinition = $schemaDefinition; | |
$this->schemaBuilder = $schemaBuilder; | |
$this->parser = $parser; | |
$this->resolverRegistry = $resolverRegistry; | |
$this->options = $options; | |
$this->errorHandler = $errorHandler; | |
} | |
/** | |
* @param string $query | |
* @param array $variables | |
* @param null|string $operationName | |
* | |
* @return array | |
* @throws InvariantException | |
*/ | |
public function executeQuery(string $query, array $variables, ?string $operationName): array | |
{ | |
// Build the schema | |
$schemaDocument = $this->getSchemaDocument(); | |
$schema = $this->schemaBuilder->build($schemaDocument, $this->resolverRegistry, $this->options); | |
// Validate the schema | |
$schemaValidationErrors = $this->validateSchema($schema); | |
if (!empty($schemaValidationErrors)) { | |
return (new ExecutionResult([], $schemaValidationErrors))->toArray(); | |
} | |
// Parse and validate the query | |
$documentOrErrors = $this->parseAndValidateQuery($schema, $query); | |
if (\is_array($documentOrErrors)) { | |
return $documentOrErrors; | |
} | |
// Execute the query and return the results | |
$result = execute( | |
$schema, | |
$documentOrErrors, | |
null, | |
null, | |
$variables, | |
$operationName, | |
null, | |
$this->errorHandler | |
); | |
return $result->toArray(); | |
} | |
/** | |
* @return DocumentNode | |
*/ | |
protected function getSchemaDocument(): DocumentNode | |
{ | |
$document = $this->cacheRepository->get(self::SCHEMA_DOCUMENT_CACHE_KEY); | |
if ($document === null) { | |
$document = $this->parser->parse($this->schemaDefinition, $this->options); | |
$this->cacheRepository->forever(self::SCHEMA_DOCUMENT_CACHE_KEY, $document); | |
} | |
return $document; | |
} | |
/** | |
* Validates the schema and returns any eventual errors from the validation. This method does nothing unless | |
* APP_ENV=local | |
* | |
* @param Schema $schema | |
* | |
* @return SchemaValidationException[] | |
*/ | |
protected function validateSchema(Schema $schema): array | |
{ | |
// Validate the schema when developing locally | |
if (env('APP_ENV', 'local') === 'local') { | |
return validateSchema($schema); | |
} | |
return []; | |
} | |
/** | |
* @param Schema $schema | |
* @param string $query | |
* | |
* @return DocumentNode|array the parsed and validated document, or a list of errors | |
* | |
* @throws InvariantException | |
*/ | |
protected function parseAndValidateQuery(Schema $schema, string $query) | |
{ | |
// Parse the query | |
try { | |
$document = parse($query); | |
} catch (SyntaxErrorException $error) { | |
return (new ExecutionResult([], [$error]))->toArray(); | |
} | |
// Validate the query once | |
if (!$this->isValidatedQuery($query)) { | |
$validationErrors = validate($schema, $document); | |
if (!empty($validationErrors)) { | |
return (new ExecutionResult([], $validationErrors))->toArray(); | |
} | |
$this->markQueryAsValidated($query); | |
} | |
return $document; | |
} | |
/** | |
* @param string $query | |
* | |
* @return bool | |
*/ | |
protected function isValidatedQuery(string $query): bool | |
{ | |
$validatedQueryHashes = $this->cacheRepository->get(self::QUERY_VALIDATION_CACHE_KEY, []); | |
$queryHash = self::calculateQueryHash($query); | |
return \in_array($queryHash, $validatedQueryHashes, true); | |
} | |
/** | |
* @param string $query | |
*/ | |
protected function markQueryAsValidated(string $query): void | |
{ | |
$validatedQueryHashes = $this->cacheRepository->get(self::QUERY_VALIDATION_CACHE_KEY, []); | |
$queryHash = self::calculateQueryHash($query); | |
$validatedQueryHashes[] = $queryHash; | |
$this->cacheRepository->forever(self::QUERY_VALIDATION_CACHE_KEY, $validatedQueryHashes); | |
} | |
/** | |
* @param string $query | |
* | |
* @return string | |
*/ | |
protected static function calculateQueryHash(string $query): string | |
{ | |
return \md5($query); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment