简体   繁体   中英

Cannot query field in GraphQL (Platform API, Symfony)

I am working with Symfony and Platform API to implement a GraphQL API. My goal is to expose different fields, depending on whether the user is logged in. The email should only be displayed if the user is logged in and is the user. Therefore I added the group user:read:self.

/**
 * @ORM\Column(type="string", length=180, unique=true)
 * @Groups({"user:read:self"})
 */
private $email;

Then I implemented a normalizer which adds the group to the context if the user is logged in:

public function normalize($object, string $format = null, array $context = [])
{
    echo "test";

    // checks whether the currently logged in user is
    // this user

    $isCurrentUser = $this->currentUser() == $object;

    if ($isCurrentUser) {
        $context['groups'][] = 'user:read:self';
    }

    $context[self::ALREADY_CALLED] = true;

    return $this->normalizer->normalize($object, $format, $context);
}

The normalizer is in fact getting called for the JSON API and GraphQL API. This works in the JSON API:

{
  "@context": "/api/contexts/User",
  "@id": "/api/users",
  "@type": "hydra:Collection",
  "hydra:member": [
    {
      "@id": "/api/users/1",
      "@type": "User",
      "email": "test@example.com",
      "animals": [],
      "friends": []
    },
    {
      "@id": "/api/users/2",
      "@type": "User",
      "animals": [],
      "friends": []
    }
  ],
  "hydra:totalItems": 2
}

I am logged in as user with id 1 and I can see the email. I can't see the email of user 2.

Then in GraphQLi I query the following and an error, even though I am logged in as user 1. I checked that the normalizer is getting called for the GraphQL query. The normalizer works and adds the group, however it appears that GraphQL does not read the context correctly:

{
  user(id: "/api/users/1") {
    email
  }
}

...
"message": "Cannot query field \"email\" on type \"User\".",
...

The short answer: You have to add a getter.

The long answer: from Symfonycast (excellent course by the way) There are actually a bunch of different "normalizer" classes that help with this job - like one that's really good at converting DateTime objects to a string and back. But the main class - the one at the heart of this process - is called the ObjectNormalizer. Behind the scenes, it uses another Symfony component called PropertyAccess, which has one superpower: if you give it a property name, like title, it's really good at finding and using getter and setter methods to access that property.

In other words, when API platform tries to "normalize" an object into an array, it uses the getter and setter methods to do that!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM