graphql-php
graphql-php copied to clipboard
Pass custom serialize function to EnumType via config
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;
}
In Lighthouse, we have extended the EnumType
to be a wrapper around bensampo/laravel-enum
:
- Implementation: https://github.com/nuwave/lighthouse/blob/master/src/Schema/Types/LaravelEnumType.php
- Usage: https://github.com/nuwave/lighthouse/blob/master/tests/Unit/Schema/Types/LaravelEnumTypeTest.php
I hope that gives you some idea on how you can implement such a type yourself.
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.
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.
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.
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;
}
}