Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] resolver implementation #753

Open
bartv2 opened this issue Aug 23, 2020 · 2 comments
Open

[RFC] resolver implementation #753

bartv2 opened this issue Aug 23, 2020 · 2 comments
Labels

Comments

@bartv2
Copy link
Contributor

bartv2 commented Aug 23, 2020

Q A
Bug report? no
Feature request? no
BC Break report? no
RFC? yes
Version/Branch 1.0-dev

I was looking how to use an attached query provider and get the parent value into the method. Not sure if that is even possible at the moment, but i found #538, #542 and #708 and i really liked the resolver idea.

I created the expression-function below to try this out. It's still missing a lot of functionality and this should probably be done at a level higher. But it works for simple functions, and is a start for a discussion. I think the 3rd parameter can be extracted from the ResolveInfo object.

With a method like

    public function posts(?string $after, ?int $first, ?string $before, ?int $last): Connection

and a resolver like

@=actionResolver('App\\GraphQL\\Query\\PostsProviders', 'posts', {after: "String", first: "Int", before: "String", last: "Int"})

generates code like

    return $globalVariables->get('container')->get('App\\GraphQL\\Query\\PostsProviders')->posts($args["after"], $args["first"], $args["before"], $args["last"]);

Or you could do this:
With a method like below and a relay-connection args builder

    public function posts(User $parentValue, Argument $args): Connection

and a resolver like

@=actionResolver('App\\GraphQL\\Query\\PostsProviders', 'posts', {})

generates code like

    return $globalVariables->get('container')->get('App\\GraphQL\\Query\\PostsProviders')->posts($value, $args);
namespace App\GraphQL\ExpressionLanguage;

use Overblog\GraphQLBundle\ExpressionLanguage\ExpressionFunction;
use Overblog\GraphQLBundle\Definition\ArgumentInterface;

class ActionResolver extends ExpressionFunction
{
    public function __construct()
    {
        parent::__construct(
            'actionResolver',
            function (string $classString, string $methodString, string $argsString = '[]') {
                $className = stripslashes(trim($classString, '"'));
                $method = trim($methodString, '"');
                $args = eval('return '.$argsString.';');
                $reflectionClass = new \ReflectionClass($className);
                $reflectionMethod = $reflectionClass->getMethod($method);
                $arguments = [];
                foreach ($reflectionMethod->getParameters() as $index => $parameter) {
                    $argument = $this->getCallArgument($parameter, $args);
                    if ($argument === null && !$parameter->isOptional()) {
                        throw new \Exception('bla');
                    }
                    $arguments[] = $argument;
                }
                return ($this->generateServiceCall($className, $method, $arguments));
            },
            fn ($_, callable $target, array $args) => dump($target, $args)
        );
    }

    private function getCallArgument(\ReflectionParameter $parameter, array $args): ?string
    {
        if (isset($args[$parameter->getName()])) {
            return '$args["'.$parameter->getName().'"]';
        }
        if (is_a($parameter->getType()->getName(), ArgumentInterface::class, true)) {
            return '$args';
        }
        if ($parameter->getName() === 'parentValue') {
            return '$value';
        }
        return null;
    }

    private function generateServiceCall(string $class, string $method, array $args)
    {
        $serviceId = addslashes($class);
        return "$this->globalVars->get('container')->get('$serviceId')"
            . "->$method(" . implode(', ', $args) . ")";
    }
}
@bartv2
Copy link
Contributor Author

bartv2 commented Sep 5, 2020

@mcg-web @Vincz @akomm @mavimo @murtukov I know you are all busy, but is this something to make a real implementation proposal for or isn't this worth pursuing?

@mcg-web
Copy link
Member

mcg-web commented Sep 5, 2020

Yes @bartv2 sorry for late reply, since #708 rewrite almost completely the way resolvers definitions. It will better to wait until this totally push, to see how we can implement other part depending on this. I'll try to push this before next weekend.

@murtukov murtukov added the RFC label Nov 14, 2020
@murtukov murtukov changed the title RFC resolver implementation [RFC] resolver implementation Nov 14, 2020
@Vincz Vincz mentioned this issue Dec 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants