In Lighthouse I have an Enum like this
<code><?php
namespace AppEnums;
use GraphQLTypeDefinitionDescription;
#[Description(description: 'Size')]
enum Size: string
{
case S = 's';
case M = 'm';
case L = 'l';
case XL = 'xl';
}
</code>
<code><?php
namespace AppEnums;
use GraphQLTypeDefinitionDescription;
#[Description(description: 'Size')]
enum Size: string
{
case S = 's';
case M = 'm';
case L = 'l';
case XL = 'xl';
}
</code>
<?php
namespace AppEnums;
use GraphQLTypeDefinitionDescription;
#[Description(description: 'Size')]
enum Size: string
{
case S = 's';
case M = 'm';
case L = 'l';
case XL = 'xl';
}
In a service provider I register it like this:
<code> $typeRegistry->register(new PhpEnumType(Size::class));
</code>
<code> $typeRegistry->register(new PhpEnumType(Size::class));
</code>
$typeRegistry->register(new PhpEnumType(Size::class));
This works all fine.
Now, for some input I want to validate it so that only L
and XL
are valid for mySize
I was thinking something like this
<code>input SomeInput {
mySize: Size @rules(apply: ["in:L,XL"])
}
</code>
<code>input SomeInput {
mySize: Size @rules(apply: ["in:L,XL"])
}
</code>
input SomeInput {
mySize: Size @rules(apply: ["in:L,XL"])
}
But this throws an error
<code>"statusCode": 500,
"debugMessage": "Object of class App\Enums\Size could not be converted to string",
"file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Validation/Concerns/ValidatesAttributes.php",
</code>
<code>"statusCode": 500,
"debugMessage": "Object of class App\Enums\Size could not be converted to string",
"file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Validation/Concerns/ValidatesAttributes.php",
</code>
"statusCode": 500,
"debugMessage": "Object of class App\Enums\Size could not be converted to string",
"file": "/var/www/html/vendor/laravel/framework/src/Illuminate/Validation/Concerns/ValidatesAttributes.php",
Is there a way to accomplish this without creating my own custom rule?
Since there doesn’t seem to be any way check using just what Lighthouse provides I eneded up creating my own custom rule:
<code><?php
declare(strict_types=1);
namespace AppRules;
use BackedEnum;
use Closure;
use Exception;
use IlluminateContractsValidationValidationRule;
use IlluminateSupportArr;
use IlluminateSupportFacadesValidator;
use IlluminateValidationValidator as ValidationValidator;
use ReflectionClass;
class InEnum implements ValidationRule
{
public static function register(): void
{
Validator::extend('in_enum', self::class . '@passes');
Validator::replacer('in_enum', function ($message, $attribute, $rule, $parameters, $validator) {
$data = $validator->getData();
$value = Arr::get($data, $attribute);
return (new self)->message($value, $parameters);
});
}
/**
* @var array<int,string> $parameters
*/
private array $parameters;
/**
* @param array<int,string> $parameters
*/
public function __construct(array $parameters = [])
{
$this->parameters = $parameters;
}
/**
* Get the validation error message.
*
* @return string
*/
public function message(BackedEnum $value, array $parameters): string
{
return __('general.validation.in_enum', ['enumClass' => (new ReflectionClass($value))->getShortName(), 'enumValue' => strtoupper($value->value), 'validValues' => implode(', ', $parameters)]);
}
/**
* Check if the rule passes based on the given arguments.
* @param string $attribute
* @param BackedEnum | null $value If $value is `null` the rule passes. To prevent this add a "required" rule as well.
* @param array<int,string> $parameters
* @return bool
*/
public function passes(string $attribute, BackedEnum|null $value, array $parameters, ValidationValidator|null $validator = null): bool
{
return ($value == null) || in_array(strtoupper($value->value), $parameters);
}
/**
* Run the validation rule.
* @param string $attribute
* @param mixed $value
* @param Closure(string): PotentiallyTranslatedString $fail
* @return void
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
throw new Exception('This functionality has not been implemented yet!');
}
}
</code>
<code><?php
declare(strict_types=1);
namespace AppRules;
use BackedEnum;
use Closure;
use Exception;
use IlluminateContractsValidationValidationRule;
use IlluminateSupportArr;
use IlluminateSupportFacadesValidator;
use IlluminateValidationValidator as ValidationValidator;
use ReflectionClass;
class InEnum implements ValidationRule
{
public static function register(): void
{
Validator::extend('in_enum', self::class . '@passes');
Validator::replacer('in_enum', function ($message, $attribute, $rule, $parameters, $validator) {
$data = $validator->getData();
$value = Arr::get($data, $attribute);
return (new self)->message($value, $parameters);
});
}
/**
* @var array<int,string> $parameters
*/
private array $parameters;
/**
* @param array<int,string> $parameters
*/
public function __construct(array $parameters = [])
{
$this->parameters = $parameters;
}
/**
* Get the validation error message.
*
* @return string
*/
public function message(BackedEnum $value, array $parameters): string
{
return __('general.validation.in_enum', ['enumClass' => (new ReflectionClass($value))->getShortName(), 'enumValue' => strtoupper($value->value), 'validValues' => implode(', ', $parameters)]);
}
/**
* Check if the rule passes based on the given arguments.
* @param string $attribute
* @param BackedEnum | null $value If $value is `null` the rule passes. To prevent this add a "required" rule as well.
* @param array<int,string> $parameters
* @return bool
*/
public function passes(string $attribute, BackedEnum|null $value, array $parameters, ValidationValidator|null $validator = null): bool
{
return ($value == null) || in_array(strtoupper($value->value), $parameters);
}
/**
* Run the validation rule.
* @param string $attribute
* @param mixed $value
* @param Closure(string): PotentiallyTranslatedString $fail
* @return void
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
throw new Exception('This functionality has not been implemented yet!');
}
}
</code>
<?php
declare(strict_types=1);
namespace AppRules;
use BackedEnum;
use Closure;
use Exception;
use IlluminateContractsValidationValidationRule;
use IlluminateSupportArr;
use IlluminateSupportFacadesValidator;
use IlluminateValidationValidator as ValidationValidator;
use ReflectionClass;
class InEnum implements ValidationRule
{
public static function register(): void
{
Validator::extend('in_enum', self::class . '@passes');
Validator::replacer('in_enum', function ($message, $attribute, $rule, $parameters, $validator) {
$data = $validator->getData();
$value = Arr::get($data, $attribute);
return (new self)->message($value, $parameters);
});
}
/**
* @var array<int,string> $parameters
*/
private array $parameters;
/**
* @param array<int,string> $parameters
*/
public function __construct(array $parameters = [])
{
$this->parameters = $parameters;
}
/**
* Get the validation error message.
*
* @return string
*/
public function message(BackedEnum $value, array $parameters): string
{
return __('general.validation.in_enum', ['enumClass' => (new ReflectionClass($value))->getShortName(), 'enumValue' => strtoupper($value->value), 'validValues' => implode(', ', $parameters)]);
}
/**
* Check if the rule passes based on the given arguments.
* @param string $attribute
* @param BackedEnum | null $value If $value is `null` the rule passes. To prevent this add a "required" rule as well.
* @param array<int,string> $parameters
* @return bool
*/
public function passes(string $attribute, BackedEnum|null $value, array $parameters, ValidationValidator|null $validator = null): bool
{
return ($value == null) || in_array(strtoupper($value->value), $parameters);
}
/**
* Run the validation rule.
* @param string $attribute
* @param mixed $value
* @param Closure(string): PotentiallyTranslatedString $fail
* @return void
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
throw new Exception('This functionality has not been implemented yet!');
}
}
It can be registered in the boot of the AppServiceProvider
like this:
<code> /**
* Bootstrap any application services.
*/
public function boot(): void
{
InEnum::register();
}
</code>
<code> /**
* Bootstrap any application services.
*/
public function boot(): void
{
InEnum::register();
}
</code>
/**
* Bootstrap any application services.
*/
public function boot(): void
{
InEnum::register();
}
..and used like this:
<code>input SomeInput {
mySize: Size @rules(apply: ["in_enum:L,XL"])
}
</code>
<code>input SomeInput {
mySize: Size @rules(apply: ["in_enum:L,XL"])
}
</code>
input SomeInput {
mySize: Size @rules(apply: ["in_enum:L,XL"])
}