Skip to content

Navigation Menu

Sign in
Sign up

How to get args, info, context or value in a resolver declared with #[GQL\Query]? #1160

Unanswered
mathroc asked this question in Q&A
Discussion options

I'm implementing a resolver that add a field to an existing type and I want to access the the value of this object type (to get its id and do some sql queries for example)

I might have missed it but I couldn't find how to do this easily. I first tried something like this:

#[GQL\Provider]
final class UserExtension
{
 #[GQL\Query(targetTypes: 'User')]
 public function something(User $user): int
 {
 return $this->computeSomething($user->id);
 }
}

hoping that it would get auto-injected, but it's not (I was not really expecting to work, but it would be nice to be able to implement something like that, something à la Symfony ValueResolverInterface like discussed in #875 would be nice)

next step was to specify the $resolve argument of #[GQL\Query], and after a few tries I go it working with this:

#[AsAlias('gql.user.something', public: true)]
#[GQL\Provider]
final class UserExtension
{
 #[GQL\Query(
 targetTypes: 'User',
 name: 'something',
 resolve: '@=call(service("gql.user.something").something, [value])',
 )]
 public function fake(): array
 {
 throw new \LogicException('TODO: figure out how we can get rid of this fake method');
 }
 public function something(User $user): int
 {
 return $this->computeSomething($user->id);
 }
}

but this means:

  • I need to make the service (or an alias as in my example) public to be able to call it in the resolve: expression
  • I can't have arguments on the method with the #[GQL\Query] attribute as the bundle would try to expose them as GraphQL arguments

but at least it works :)

then I had a case where I want to have the value and a GraphQL argument, so I tried something like this:

#[AsAlias('gql.user.something', public: true)]
#[GQL\Provider]
final class UserExtension
{
 #[GQL\Query(
 targetTypes: 'User',
 name: 'something',
 resolve: '@=call(service("gql.user.something").something, [value, ...args])',
 )]
 public function fake(int $foo): array
 {
 throw new \LogicException('TODO: figure out how we can get rid of this fake method');
 }
 public function something(User $user, int $foo): int
 {
 return $this->computeSomething($user->id, $foo);
 }
}

but this doesn't work because unpacking with ... isn't supported in expressions, so [value, ...args] doesn't work.


Is there a better way to do this? I would really like to this with attributes on DTO instead of doing too much stuff "manually" so that everything is less error-prone.

maybe something like this:

#[GQL\Provider]
final class UserExtension
{
 #[GQL\Query(targetTypes: 'User')]
 public function something(
 #[GQL\Expr('value') User $user,
 int $foo,,
 ): int {
 return $this->computeSomething($user->id, $foo);
 }
}

wdyt? or again, maybe I've missed something?

thank you,

You must be logged in to vote

Replies: 2 comments 2 replies

Comment options

Hi @mathroc! You are right, the current implementation is far from ideal. We are required to make our providers public and we are fairly limited in term of parameters injection.
At the moment, the only way I see would be something like this (didn't tried it):

#[AsAlias('gql.user.something', public: true)]
#[GQL\Provider]
final class UserExtension
{
 #[GQL\Query(
 targetTypes: 'User',
 name: 'something',
 resolve: '@=call(service("gql.user.something").something, [value, args["foo"]])',
 )]
 #[GQL\Arg(name='foo', type: 'Int')]
 public function something(User $user, int $foo): int
 {
 return $this->computeSomething($user->id, $foo);
 }
}
You must be logged in to vote
1 reply
Comment options

thx! didn't think about args["foo"] 🤦 that part works 👌

but I still need the intermediate function, without it, I have this error:

Argument n°1 "$user" on method "something" cannot be auto-guessed from the following type guessers: [Type Hint] No corresponding GraphQL scalar,enum,input found for class "User"

an easy fix would be to implement something like this:

public function something(#[GQL\Arg(skip: true)] User $user, int $foo): int

but it's a bit annoying to introduce this complexity for a workaround. but the more long-term solution would probably be quite more work

ps: btw, I know #[GQL\Arg] should be on the method, not the argument. would you be open to a merge request supporting them on arguments as-well?

Comment options

I think we could work from this PR: #728 if we wanted to improve the ArgumentsTransformer by allowing the users to define their owns transformer and to define a bunch automatically (like ResolveInfo, UserInterface, ValueInterface) specifically for the annotations/attributes.
@mcg-web was working on global improvements on the resolution but it was 3 years ago and I don't think he has a lot of time this day.
I don't have either, but I'll be willing to help you as much as I can if you want.

You must be logged in to vote
1 reply
Comment options

Interesting :) will have a look

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet
2 participants

AltStyle によって変換されたページ (->オリジナル) /