besmartand-pro/graphqlite-symfony-validator-bridge
Bridge package connecting Symfony Validator with GraphQLite, enabling automatic validation of GraphQL input/arguments using Symfony constraints and returning structured validation errors in GraphQL responses. Suitable for Symfony apps using GraphQLite.
Leverage GraphQLite’s schema definitions to embed Symfony constraints directly, reducing resolver clutter.
use GraphQL\Type\Definition\InputType;
use GraphQL\Type\Definition\Type;
use Symfony\Component\Validator\Constraints as Assert;
use Besmartand\GraphQLite\SymfonyValidatorBridge\Annotation\ValidatedInput;
/**
* @ValidatedInput({
* "email": {"constraints": {"Email": {}}},
* "password": {
* "constraints": {
* "NotBlank": {},
* "Length": {"min": 8}
* }
* }
* })
*/
$inputType = new InputType([
'name' => 'UserInput',
'fields' => [
'email' => Type::string(),
'password' => Type::string(),
],
]);
Pros:
Cons:
doctrine/annotations).Use the bridge to apply validation rules dynamically in resolvers.
use Besmartand\GraphQLite\SymfonyValidatorBridge\ValidatorBridge;
public function resolve($root, $args)
{
$validator = app(ValidatorBridge::class);
// Dynamic rules based on context
$rules = [
'email' => 'required|email',
'password' => $args['isAdmin'] ? 'required|min:12' : 'required|min:8',
];
$errors = $validator->validate($args, $rules);
if ($errors) {
throw new GraphQLValidationError($errors);
}
// Proceed
}
Pros:
Cons:
Extract validation logic into services to avoid duplication.
// app/Services/UserInputValidator.php
class UserInputValidator
{
protected $validator;
public function __construct(ValidatorBridge $validator)
{
$this->validator = $validator;
}
public function validate(array $input): array
{
return $validator->validate($input, [
'email' => [
new Assert\NotBlank(),
new Assert\Email(),
],
'password' => [
new Assert\NotBlank(),
new Assert\Length(['min' => 8]),
],
]);
}
}
Usage in Resolver:
public function resolve($root, $args)
{
$validator = app(UserInputValidator::class);
$errors = $validator->validate($args);
if ($errors) {
throw new GraphQLValidationError($errors);
}
// ...
}
Pros:
Cons:
Validate complex input structures (e.g., arrays, objects).
$validator->validate($args, [
'items' => new Assert\All([
new Assert\Valid(),
new Assert\Type('array'),
new Assert\Count(['min' => 1]),
]),
'items.*.name' => 'required|string|max:255',
'items.*.price' => 'type:float|min:0',
]);
Pros:
Cons:
Reuse existing Laravel validation logic in GraphQL.
use App\Http\Requests\StoreUserRequest;
use Besmartand\GraphQLite\SymfonyValidatorBridge\ValidatorBridge;
public function resolve($root, $args)
{
$validator = app(ValidatorBridge::class);
$request = new StoreUserRequest();
$request->merge($args);
$validator->validate($request->validated(), $request->rules());
// ...
}
Pros:
Cons:
Map Symfony validation errors to GraphQL-friendly formats.
use Symfony\Component\Validator\ConstraintViolationListInterface;
use GraphQL\Error\FormattedError;
public function handleValidationErrors(ConstraintViolationListInterface $errors): array
{
return array_map(function ($error) {
return new FormattedError([
'message' => $error->getMessage(),
'path' => $error->getPropertyPath(),
'code' => 'VALIDATION_ERROR',
'extensions' => [
'constraint' => get_class($error->getConstraint()),
],
]);
}, iterator_to_array($errors));
}
Usage:
try {
$validator->validate($args, $rules);
} catch (ValidationException $e) {
throw new GraphQLValidationError($this->handleValidationErrors($e->getErrors()));
}
Pros:
Cons:
Optimize performance for repeated validations (e.g., in loops).
use Illuminate\Support\Facades\Cache;
public function validateCached(array $input, array $rules, string $cacheKey)
{
return Cache::remember($cacheKey, now()->addMinutes(10), function () use ($input, $rules) {
return app(ValidatorBridge::class)->validate($input, $rules);
});
}
Usage:
$errors = $this->validateCached($args, $rules, "validation_{$args['email']}");
Pros:
Cons:
Write focused tests for validation rules.
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
class UserInputValidatorTest extends ConstraintValidatorTestCase
{
public function testValidInput()
{
$validator = app(ValidatorBridge::class);
$input = ['email' => 'test@example.com', 'password' => 'secure123'];
$errors = $validator->validate($input, $this->getRules());
$this->assertEmpty($errors);
}
public function testInvalidEmail()
{
$validator = app(ValidatorBridge::class);
$input = ['email' => 'invalid-email', 'password' => 'secure123'];
$errors = $validator->validate($input, $this->getRules());
$this->assertCount(1, $errors);
}
protected function getRules(): array
{
return [
'email' => 'required|email',
'password' => 'required|min:8',
];
}
}
Pros:
Cons:
Schema Validation Mismatch
graphql-php to enforce consistency.Performance Overhead
@Cache decorators for resolvers.tideways/xhprof to identify bottlenecks.Error Handling Gaps
ValidationException can crash GraphQL responses.ValidationException in resolvers.$schema->setErrorHandler(function ($errors) {
return array_map(function ($error) {
if ($error instanceof ValidationException) {
return $this->handleValidationErrors($error->getErrors());
}
return $error;
}, $errors);
});
Annotation Parsing Failures
@ValidatedInput annotations may not parse correctly.doctrine/annotations is installed:
composer require doctrine/
How can I help you explore Laravel packages today?