Skip to content

Instantly share code, notes, and snippets.

@marvinrabe
Created May 14, 2019 06:56
Show Gist options
  • Save marvinrabe/85f9ac19a052137fbcf7ee446b77878a to your computer and use it in GitHub Desktop.
Save marvinrabe/85f9ac19a052137fbcf7ee446b77878a to your computer and use it in GitHub Desktop.
Nuwave Lighthouse Resolve function changes
<?php
namespace App\GraphQL;
use GraphQL\Type\Definition\ResolveInfo;
use Illuminate\Support\Facades\Validator;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
class Request
{
protected $rootValue;
protected $arguments;
protected $context;
protected $resolveInfo;
/**
* @param mixed $rootValue Usually contains the result returned from the parent field.
* @param mixed[] $args The arguments that were passed into the field.
* @param GraphQLContext $context Arbitrary data that is shared between all fields of a single query.
* @param ResolveInfo $resolveInfo Information about the query itself, such as the execution state, the field name, path to the field from the root, and more.
*/
public function __construct($rootValue, array $args, GraphQLContext $context, ResolveInfo $resolveInfo)
{
$this->rootValue = $rootValue;
$this->arguments = $args;
$this->context = $context;
$this->resolveInfo = $resolveInfo;
}
/**
* Usually contains the result returned from the parent field.
* @return mixed
*/
public function rootValue()
{
return $this->rootValue;
}
/**
* Information about the query itself, such as the execution state, the field name, path to the field from the root, and more.
* @return ResolveInfo
*/
public function resolveInfo()
{
return $this->resolveInfo;
}
/**
* Arbitrary data that is shared between all fields of a single query.
* @return GraphQLContext
*/
public function context()
{
return $this->context;
}
/**
* Return array of parameters to be used in dependency resolving.
* @return array
*/
public function arguments()
{
return $this->arguments;
}
/**
* Get the key / value list of parameters without null values.
* @return array
*/
public function argumentsWithoutNulls()
{
return array_filter($this->arguments(), function ($p) {
return !is_null($p);
});
}
}
<?php
namespace App\GraphQL;
use GraphQL\Type\Definition\ResolveInfo;
use Illuminate\Container\Container;
use Illuminate\Contracts\Routing\UrlRoutable;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Support\Str;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
use ReflectionMethod;
use ReflectionParameter;
use RuntimeException;
abstract class Resolver
{
/**
* The container instance.
* @var Container
*/
protected $container;
/**
* Create a new resolver instance.
* @param Container $container
* @return void
*/
public function __construct(Container $container)
{
$this->container = $container;
}
public function resolve($rootValue, array $args, GraphQLContext $context, ResolveInfo $resolveInfo)
{
$request = new Request($rootValue, $args, $context, $resolveInfo);
$parameters = $this->resolveDependencies($request);
return $this->respond(...array_values($parameters));
}
protected function resolveDependencies(Request $request)
{
$reflection = new ReflectionMethod($this, 'respond');
$result = [];
foreach ($reflection->getParameters() as $key => $parameter) {
$result[$key] = $this->resolveDependency($request, $parameter);
}
return $result;
}
protected function resolveDependency(Request $request, ReflectionParameter $parameter)
{
$parameters = $request->argumentsWithoutNulls();
if ($parameter->getClass()) {
if ($parameter->getClass()->name == Request::class) {
return $request;
}
$instance = $this->container->make($parameter->getClass()->name);
if ($model = $this->bindEloquentModels($request, $instance, $parameter->name)) {
return $model;
}
return $instance;
}
if (isset($parameters[$parameter->name])) {
return $parameters[$parameter->name];
}
if ($parameter->isDefaultValueAvailable()) {
return $parameter->getDefaultValue();
}
throw new RuntimeException("No default value for {$parameter->name} in ".static::class);
}
protected function bindEloquentModels(Request $request, $instance, $name)
{
if (!$instance instanceof UrlRoutable) {
return null;
}
$parameters = $request->argumentsWithoutNulls();
if (!$parameterName = static::getEloquentParameterName($name, $parameters)) {
return null;
}
$parameterValue = $parameters[$parameterName];
if (!$model = $instance->resolveRouteBinding($parameterValue)) {
throw (new ModelNotFoundException)->setModel(get_class($instance));
}
return $model;
}
protected static function getEloquentParameterName($name, $parameters)
{
if (array_key_exists($name, $parameters)) {
return $name;
}
if (array_key_exists($snakedName = Str::snake($name), $parameters)) {
return $snakedName;
}
if (array_key_exists('id', $parameters)) {
return 'id';
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment