2

I want to use value object or string object in my project (DDD, Hexagonal, POO no question). I can work perfectly in most cases but I couldn't find a way to work with it in Api Platform GraphQl. I've tried Type, Normalizer and some other ways without result. I think is a schema issue that it doesn't know what to do with the Email class and it is ignored.

My Email class looks like this:

class Email
{
    protected string $value;
    private function __construct(string $email)
    {
        $this->value = $email;
    }

    public static function fromString(string $email): Email
    {
        Assert::maxLength($email, 255);
        Assert::minLength($email, 3);
        Assert::email($email);

        return new self($email);
    }



    public function value(): string
    {
        return $this->value;
    }

    public function __toString()
    {
        return $this->value();
    }
}

And use it in the User:

/**
 * @ApiResource
 * @ORM\Table(name="users")
 * @ORM\Entity()
 */
class User
{

    /**
     * @Groups("user")
     * @ORM\Column(type="email", length=180, unique=true, nullable=true)
     */
    protected ?Email $email;
}

How many things I have to do to get in my graphql:\

query {
  users {
    edges {
      node {
        id
        email
      }
    }
  }
}

And get for example:

{
  "data": {
    "users": {
      "edges": [
        {
          "node": {
            "id": "/api/users/ac9f782e-e56e-4f36-9d78-bf563aa8f3e5",
            "email": "user@emaple.com"
          }
        }
      ]
    }
  }
}

PD: I already have doctrine persistance stored as plain string, I can query and save the User object without any issue, but I could be able to do it in api-platform graphql due this error:

{
  "errors": [
    {
      "message": "Cannot query field \"email\" on type \"User\".",
      "extensions": {
        "category": "graphql"
      },
      "locations": [
        {
          "line": 7,
          "column": 9
        }
      ]
    }
  ]

}

1 Answers1

1

I made an incorrect check on my TypeConverter, so this is all I have to do in order to work propertly, create a simple converter:

final class TypeConverter implements TypeConverterInterface
{
    private TypeConverterInterface $defaultTypeConverter;

    public function __construct(TypeConverterInterface $defaultTypeConverter)
    {
        $this->defaultTypeConverter = $defaultTypeConverter;
    }

    /**
     * {@inheritdoc}
     */
    public function convertType(Type $type, bool $input, ?string $queryName, ?string $mutationName, string $resourceClass, string $rootResource, ?string $property, int $depth)
    {
        if (Email::class === $resourceClass) {
            return GraphQLType::string();
        }

        return $this->defaultTypeConverter->convertType($type, $input, $queryName, $mutationName, $resourceClass, $rootResource, $property, $depth);
    }

    /**
     * {@inheritdoc}
     */
    public function resolveType(string $type): ?GraphQLType
    {
        return $this->defaultTypeConverter->resolveType($type);
    }
}