graphql-php icon indicating copy to clipboard operation
graphql-php copied to clipboard

Ability to implement ID coercion (input and output)

Open akomm opened this issue 5 years ago • 4 comments

Thoughts based on the spec: https://graphql.github.io/graphql-spec/June2018/#sec-ID

In general, ID should coerce to string on the output side and from string or int on the input side.

Some points on the expected behavior when coercing on input and outside side - excerpt from the spec:

Result (Output) Coercion: [...] GraphQL servers should coerce as appropriate given the ID formats they expect. When coercion is not possible they must raise a field error.

Input Coercion: [...] input value should be coerced to ID as appropriate for the ID formats a given GraphQL server expects. Any other input value, [..], must raise a query error indicating an incorrect type.

Given current ID implementation, it is not possible to implement the coerce logic. Neither for input, nor the output side. It is also not possible to give an error on the input or output side, when coercion to the ID format expected is not possible. This must be done in the resolver itself, over and over again.

My proposal is to allow for custom coercion logic. For example using an interface, like the following:

interface CoerceID
{
    /**
     * @var string|int $id
     * @return mixed internal ID type
     */
    public function fromInput($id);

    /**
     * @param ValueNode $id
     * @return mixed internal ID type
     */
    public function fromInputLiteral(ValueNode $id);

    /**
     * @param mixed $id internal ID type
     * @return string
     */
    public function toOutput($id): string;
}

Making it BC should be possible, by having the current behavior as a default implementation. The library user should have the ability to provide a custom implementation and for example produce type error (on the input side) or field error (on the output side), when coercion was not possible.

The interfaces accepts string and int on the input side, and expects string on the output side, as specified in spec. The internal server type is up to the library user.

akomm avatar Oct 14 '19 12:10 akomm

See https://github.com/webonyx/graphql-php/issues/401 on how to override internal types

vladar avatar Oct 14 '19 12:10 vladar

I missed that one @vladar , you was not against override of internal types?

mcg-web avatar Oct 14 '19 12:10 mcg-web

@vladar If I might quote you: But note that this is just an escape hatch until we find a better way to do this.

And you are right. I do not think overriding any internal type would make sense, when they are strictly defined. ID is an exclusion here. So I checked the references issues (where you commented) and found they all actually just want to work with ID coercion!

  • https://github.com/webonyx/graphql-php/issues/353
  • https://github.com/webonyx/graphql-php/issues/301#issuecomment-403223102

So this is why I propose to not override the internal types, but have the ability to specify ID coercion logic.

akomm avatar Oct 14 '19 12:10 akomm

That's why it is not quite documented %) If you are ready to tackle this and prepare a PR - I will be happy to accept it!

vladar avatar Oct 14 '19 12:10 vladar