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

Pass custom serialize function to EnumType via config #775

Open
oligus opened this issue Feb 5, 2021 · 5 comments
Open

Pass custom serialize function to EnumType via config #775

oligus opened this issue Feb 5, 2021 · 5 comments

Comments

@oligus
Copy link

oligus commented Feb 5, 2021

Is it possible to have custom enum types, like myclabs/php-enum?

It is possible via TypeConfigDecorator to replace enum values with php-enum, but the serialize function is not overridden from what I can see. The serialize function is never invoked, instead the default serialize function in EnumType is run. So I guess the question is how I can serialize custom enum types?

if ($typeConfig['astNode'] instanceof EnumTypeDefinitionNode) {
    $typeConfig['values'] = EnumValueMapper::map($typeConfig); // returns array of key => enum object 
    $typeConfig = array_merge($typeConfig, [
        'serialize' => function() {
            die('serialize');
        }
    ]);

    return $typeConfig;
}
@spawnia
Copy link
Collaborator

spawnia commented Feb 5, 2021

In Lighthouse, we have extended the EnumType to be a wrapper around bensampo/laravel-enum:

I hope that gives you some idea on how you can implement such a type yourself.

@spawnia spawnia closed this as completed Feb 5, 2021
@oligus
Copy link
Author

oligus commented Feb 5, 2021

Thank you for quick answer! I think you lost me (or me you) :-)

I have a schema file schema.graphql that I read together with TypeConfigDecorator:

$schema = BuildSchema::build($schemaFile, TypeConfigDecorator::resolve());

After which I run the GraphQL::executeQuery with a root resolver. With a programatically built schema, no problem to override the enums at all, similar to your approach with a type registry, but reading the schema directly I don't understand how to override the enums.

It might be worth to mention that I can override scalars in the TypeConfigDecorator with serialize, parseValue, parseLiteral functions that override the original function.

@spawnia
Copy link
Collaborator

spawnia commented Feb 5, 2021

I suppose that what you are trying to do is not possible with the type config decorator. It looks like the reference implementation does not support passing a custom serialize function through the config; since we usually follow them we don't either. https://graphql.org/graphql-js/type/#graphqlenumtype That is why I went with a subclass to allow for a custom serialize method.

Let's turn this into a feature request then, since I do think it is reasonable. I do like functional composition over inheritance anyways. Do you care enough to try and implement a PR? EnumType and the corresponding test would need to be adapted.

@spawnia spawnia reopened this Feb 5, 2021
@oligus
Copy link
Author

oligus commented Feb 5, 2021

Thank you for your reply. Let me take a look at it in the coming days and I can come back with my findings on this thread.

@spawnia spawnia changed the title Custom enum types (myclabs/php-enum) Pass custom serialize function to EnumType via config Feb 5, 2021
@ctadlock
Copy link

For anyone just using this project.. using @spawnia 's pattern above this is a simple extended class to handle this:

use GraphQL\Type\Definition\EnumType as GraphQLEnumType;
use BenSampo\Enum\Enum as BenSampoEnum;
use InvalidArgumentException;

// https://github.com/webonyx/graphql-php/issues/775
// https://github.com/nuwave/lighthouse/blob/master/src/Schema/Types/LaravelEnumType.php

class EnumClassType extends GraphQLEnumType
{
    protected $enumClass;

    public function __construct($enumClass, $config)
    {
        if (! is_subclass_of($enumClass, BenSampoEnum::class)) {
            throw new InvalidArgumentException(
                "Must pass an instance of \BenSampo\Enum\Enum, got {$enumClass}."
            );
        }

        $this->enumClass = $enumClass;

        parent::__construct($config);
    }

    public function serialize($value): string
    {
        if (! $value instanceof BenSampoEnum) {
            $value = $this->enumClass::fromValue($value);
        }

        return $value->key;
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants