mirror of
https://github.com/retailcrm/graphql-php.git
synced 2024-11-25 14:26:08 +03:00
Allow providing default field resolver for execution call
This commit is contained in:
parent
9f4980ce49
commit
78d9ba0d5e
@ -44,12 +44,17 @@ class ExecutionContext
|
||||
*/
|
||||
public $variableValues;
|
||||
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
public $fieldResolver;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $errors;
|
||||
|
||||
public function __construct($schema, $fragments, $root, $contextValue, $operation, $variables, $errors)
|
||||
public function __construct($schema, $fragments, $root, $contextValue, $operation, $variables, $errors, $fieldResolver)
|
||||
{
|
||||
$this->schema = $schema;
|
||||
$this->fragments = $fragments;
|
||||
@ -58,6 +63,7 @@ class ExecutionContext
|
||||
$this->operation = $operation;
|
||||
$this->variableValues = $variables;
|
||||
$this->errors = $errors ?: [];
|
||||
$this->fieldResolver = $fieldResolver;
|
||||
}
|
||||
|
||||
public function addError(Error $error)
|
||||
|
@ -89,9 +89,18 @@ class Executor
|
||||
* @param $contextValue
|
||||
* @param array|\ArrayAccess $variableValues
|
||||
* @param null $operationName
|
||||
* @param callable $fieldResolver
|
||||
* @return ExecutionResult|Promise
|
||||
*/
|
||||
public static function execute(Schema $schema, DocumentNode $ast, $rootValue = null, $contextValue = null, $variableValues = null, $operationName = null)
|
||||
public static function execute(
|
||||
Schema $schema,
|
||||
DocumentNode $ast,
|
||||
$rootValue = null,
|
||||
$contextValue = null,
|
||||
$variableValues = null,
|
||||
$operationName = null,
|
||||
$fieldResolver = null
|
||||
)
|
||||
{
|
||||
if (null !== $variableValues) {
|
||||
Utils::invariant(
|
||||
@ -106,7 +115,15 @@ class Executor
|
||||
);
|
||||
}
|
||||
|
||||
$exeContext = self::buildExecutionContext($schema, $ast, $rootValue, $contextValue, $variableValues, $operationName);
|
||||
$exeContext = self::buildExecutionContext(
|
||||
$schema,
|
||||
$ast,
|
||||
$rootValue,
|
||||
$contextValue,
|
||||
$variableValues,
|
||||
$operationName,
|
||||
$fieldResolver
|
||||
);
|
||||
$promiseAdapter = self::getPromiseAdapter();
|
||||
|
||||
$executor = new self($exeContext, $promiseAdapter);
|
||||
@ -129,6 +146,8 @@ class Executor
|
||||
* @param $contextValue
|
||||
* @param $rawVariableValues
|
||||
* @param string $operationName
|
||||
* @param callable $fieldResolver
|
||||
*
|
||||
* @return ExecutionContext
|
||||
* @throws Error
|
||||
*/
|
||||
@ -138,7 +157,8 @@ class Executor
|
||||
$rootValue,
|
||||
$contextValue,
|
||||
$rawVariableValues,
|
||||
$operationName = null
|
||||
$operationName = null,
|
||||
$fieldResolver = null
|
||||
)
|
||||
{
|
||||
$errors = [];
|
||||
@ -183,7 +203,16 @@ class Executor
|
||||
$rawVariableValues ?: []
|
||||
);
|
||||
|
||||
$exeContext = new ExecutionContext($schema, $fragments, $rootValue, $contextValue, $operation, $variableValues, $errors);
|
||||
$exeContext = new ExecutionContext(
|
||||
$schema,
|
||||
$fragments,
|
||||
$rootValue,
|
||||
$contextValue,
|
||||
$operation,
|
||||
$variableValues,
|
||||
$errors,
|
||||
$fieldResolver ?: self::$defaultFieldResolver
|
||||
);
|
||||
return $exeContext;
|
||||
}
|
||||
|
||||
@ -625,7 +654,7 @@ class Executor
|
||||
} else if (isset($parentType->resolveFieldFn)) {
|
||||
$resolveFn = $parentType->resolveFieldFn;
|
||||
} else {
|
||||
$resolveFn = self::$defaultFieldResolver;
|
||||
$resolveFn = $this->exeContext->fieldResolver;
|
||||
}
|
||||
|
||||
// The resolve function's optional third argument is a context value that
|
||||
|
@ -17,16 +17,60 @@ use GraphQL\Validator\Rules\QueryComplexity;
|
||||
class GraphQL
|
||||
{
|
||||
/**
|
||||
* This is the primary entry point function for fulfilling GraphQL operations
|
||||
* by parsing, validating, and executing a GraphQL document along side a
|
||||
* GraphQL schema.
|
||||
*
|
||||
* More sophisticated GraphQL servers, such as those which persist queries,
|
||||
* may wish to separate the validation and execution phases to a static time
|
||||
* tooling step, and a server runtime step.
|
||||
*
|
||||
* schema:
|
||||
* The GraphQL type system to use when validating and executing a query.
|
||||
* requestString:
|
||||
* A GraphQL language formatted string representing the requested operation.
|
||||
* rootValue:
|
||||
* The value provided as the first argument to resolver functions on the top
|
||||
* level type (e.g. the query object type).
|
||||
* variableValues:
|
||||
* A mapping of variable name to runtime value to use for all variables
|
||||
* defined in the requestString.
|
||||
* operationName:
|
||||
* The name of the operation to use if requestString contains multiple
|
||||
* possible operations. Can be omitted if requestString contains only
|
||||
* one operation.
|
||||
* fieldResolver:
|
||||
* A resolver function to use when one is not provided by the schema.
|
||||
* If not provided, the default field resolver is used (which looks for a
|
||||
* value or method on the source value with the field's name).
|
||||
*
|
||||
* @param Schema $schema
|
||||
* @param string|DocumentNode $requestString
|
||||
* @param mixed $rootValue
|
||||
* @param array|null $variableValues
|
||||
* @param string|null $operationName
|
||||
* @param callable $fieldResolver
|
||||
* @return Promise|array
|
||||
*/
|
||||
public static function execute(Schema $schema, $requestString, $rootValue = null, $contextValue = null, $variableValues = null, $operationName = null)
|
||||
public static function execute(
|
||||
Schema $schema,
|
||||
$requestString,
|
||||
$rootValue = null,
|
||||
$contextValue = null,
|
||||
$variableValues = null,
|
||||
$operationName = null,
|
||||
$fieldResolver = null
|
||||
)
|
||||
{
|
||||
$result = self::executeAndReturnResult($schema, $requestString, $rootValue, $contextValue, $variableValues, $operationName);
|
||||
$result = self::executeAndReturnResult(
|
||||
$schema,
|
||||
$requestString,
|
||||
$rootValue,
|
||||
$contextValue,
|
||||
$variableValues,
|
||||
$operationName,
|
||||
$fieldResolver
|
||||
);
|
||||
|
||||
if ($result instanceof ExecutionResult) {
|
||||
return $result->toArray();
|
||||
@ -40,14 +84,26 @@ class GraphQL
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as `execute`, but returns instance of ExecutionResult instead of array,
|
||||
* which can be used for custom error formatting or adding extensions to response
|
||||
*
|
||||
* @param Schema $schema
|
||||
* @param string|DocumentNode $requestString
|
||||
* @param mixed $rootValue
|
||||
* @param array|null $variableValues
|
||||
* @param string|null $operationName
|
||||
* @param callable $fieldResolver
|
||||
* @return ExecutionResult|Promise
|
||||
*/
|
||||
public static function executeAndReturnResult(Schema $schema, $requestString, $rootValue = null, $contextValue = null, $variableValues = null, $operationName = null)
|
||||
public static function executeAndReturnResult(
|
||||
Schema $schema,
|
||||
$requestString,
|
||||
$rootValue = null,
|
||||
$contextValue = null,
|
||||
$variableValues = null,
|
||||
$operationName = null,
|
||||
$fieldResolver = null
|
||||
)
|
||||
{
|
||||
try {
|
||||
if ($requestString instanceof DocumentNode) {
|
||||
@ -66,7 +122,15 @@ class GraphQL
|
||||
if (!empty($validationErrors)) {
|
||||
return new ExecutionResult(null, $validationErrors);
|
||||
} else {
|
||||
return Executor::execute($schema, $documentNode, $rootValue, $contextValue, $variableValues, $operationName);
|
||||
return Executor::execute(
|
||||
$schema,
|
||||
$documentNode,
|
||||
$rootValue,
|
||||
$contextValue,
|
||||
$variableValues,
|
||||
$operationName,
|
||||
$fieldResolver
|
||||
);
|
||||
}
|
||||
} catch (Error $e) {
|
||||
return new ExecutionResult(null, [$e]);
|
||||
|
@ -972,6 +972,44 @@ class ExecutorTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @it uses a custom field resolver
|
||||
*/
|
||||
public function testUsesACustomFieldResolver()
|
||||
{
|
||||
$query = Parser::parse('{ foo }');
|
||||
|
||||
$schema = new Schema([
|
||||
'query' => new ObjectType([
|
||||
'name' => 'Query',
|
||||
'fields' => [
|
||||
'foo' => ['type' => Type::string()]
|
||||
]
|
||||
])
|
||||
]);
|
||||
|
||||
// For the purposes of test, just return the name of the field!
|
||||
$customResolver = function ($source, $args, $context, ResolveInfo $info) {
|
||||
return $info->fieldName;
|
||||
};
|
||||
|
||||
$result = Executor::execute(
|
||||
$schema,
|
||||
$query,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$customResolver
|
||||
);
|
||||
|
||||
$expected = [
|
||||
'data' => ['foo' => 'foo']
|
||||
];
|
||||
|
||||
$this->assertEquals($expected, $result->toArray());
|
||||
}
|
||||
|
||||
public function testSubstitutesArgumentWithDefaultValue()
|
||||
{
|
||||
$schema = new Schema([
|
||||
|
Loading…
Reference in New Issue
Block a user