Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Validator Laravel Package

draw/validator

PHP validation library providing a fluent API to define rules, validate arrays/inputs, and collect errors. Lightweight and framework-agnostic, suitable for Laravel or standalone apps.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Install the Package

    composer require draw/validator
    

    This installs the package and its Symfony dependencies (symfony/validator, symfony/dependency-injection).

  2. Register the Service Provider Add the provider to config/app.php under providers:

    Draw\Validator\ValidatorServiceProvider::class,
    
  3. First Use Case: Validate a Simple Object Define a class with Symfony constraints and validate it:

    use Symfony\Component\Validator\Constraints as Assert;
    
    class UserRegistration {
        #[Assert\NotBlank]
        #[Assert\Email]
        public string $email;
    
        #[Assert\Length(min: 8)]
        public string $password;
    }
    
    // Validate the object
    $validator = app(\Symfony\Component\Validator\ValidatorInterface::class);
    $user = new UserRegistration();
    $user->email = 'invalid-email';
    $user->password = 'short';
    
    $errors = $validator->validate($user);
    foreach ($errors as $error) {
        echo $error->getPropertyPath() . ': ' . $error->getMessage() . PHP_EOL;
    }
    

    Output:

    email: This value should not be blank.
    email: This value should be a valid email address.
    password: This value should have 8 characters or more.
    
  4. Integrate with Laravel Requests Use the validator in a FormRequest or controller:

    use Illuminate\Http\Request;
    use Symfony\Component\Validator\Constraints as Assert;
    
    class StoreUserRequest extends Request {
        public function rules() {
            return [
                'email' => ['required', 'email'],
                'password' => ['required', 'min:8'],
            ];
        }
    
        public function validateWithSymfony() {
            $validator = app(\Symfony\Component\Validator\ValidatorInterface::class);
            $data = $this->validate($this->rules());
    
            // Manually map Laravel's validated data to an object
            $user = new UserRegistration();
            $user->email = $data['email'];
            $user->password = $data['password'];
    
            $errors = $validator->validate($user);
            if ($errors->count() > 0) {
                throw new \Illuminate\Validation\ValidationException($this->formatErrors($errors));
            }
        }
    
        protected function formatErrors($errors) {
            return array_map(function ($error) {
                return $error->getPropertyPath() => $error->getMessage();
            }, $errors->toArray());
        }
    }
    

Implementation Patterns

Common Workflows

1. Declarative Validation with Constraints

Use Symfony’s constraints (@Assert\*) for reusable validation logic:

use Symfony\Component\Validator\Constraints as Assert;

class Order {
    #[Assert\GreaterThan(0)]
    public int $quantity;

    #[Assert\All([
        new Assert\NotBlank(),
        new Assert\Type('string'),
    ])]
    public array $items;
}

2. Validation Groups

Validate specific subsets of properties:

$validator = app(\Symfony\Component\Validator\ValidatorInterface::class);
$errors = $validator->validate($order, ['order']);

3. Custom Constraints

Extend validation with business rules:

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

class UniqueUsernameConstraint extends Constraint {
    public $message = 'This username is already taken.';
}

class UniqueUsernameValidator extends ConstraintValidator {
    public function validate($value, Constraint $constraint) {
        if (User::where('username', $value)->exists()) {
            $this->context->buildViolation($constraint->message)
                ->addViolation();
        }
    }
}

// Register the constraint (e.g., in a service provider)
$validatorBuilder = app(\Symfony\Component\Validator\Validation::class);
$validatorBuilder->addConstraintFactory(
    new UniqueUsernameConstraintFactory()
);

4. Integrate with Laravel Form Requests

Override Laravel’s validate() to use Symfony:

class CreateOrderRequest extends FormRequest {
    public function validate() {
        $validator = app(\Symfony\Component\Validator\ValidatorInterface::class);
        $data = $this->all();

        // Convert array to object (or use a DTO)
        $order = (object) $data;
        $errors = $validator->validate($order);

        if ($errors->count() > 0) {
            throw new \Illuminate\Validation\ValidationException(
                $this->formatSymfonyErrors($errors)
            );
        }
    }

    protected function formatSymfonyErrors($errors) {
        $messages = [];
        foreach ($errors as $error) {
            $messages[$error->getPropertyPath()] = $error->getMessage();
        }
        return $messages;
    }
}

5. API Response Formatting

Convert Symfony errors to Laravel’s JSON response format:

public function handle() {
    try {
        $this->validateWithSymfony();
        // Proceed with logic
    } catch (\Illuminate\Validation\ValidationException $e) {
        return response()->json([
            'errors' => $e->errors(),
        ], 422);
    }
}

Integration Tips

Leverage Laravel’s Service Container

Bind Symfony’s ValidatorInterface to Laravel’s container for easy access:

$this->app->bind(\Symfony\Component\Validator\ValidatorInterface::class, function ($app) {
    return \Symfony\Component\Validator\Validation::createValidatorBuilder()
        ->enableAnnotationReading()
        ->getValidator();
});

Use Dependency Injection

Inject the validator into services or controllers:

use Symfony\Component\Validator\ValidatorInterface;

class OrderService {
    public function __construct(private ValidatorInterface $validator) {}

    public function createOrder(array $data) {
        $order = (object) $data;
        $errors = $this->validator->validate($order);
        if ($errors->count() > 0) {
            throw new \RuntimeException('Validation failed');
        }
        // Proceed
    }
}

Combine with Laravel Validation

Use Symfony for complex rules and Laravel for simple ones:

public function rules() {
    return [
        'email' => 'required|email', // Simple Laravel rule
        'password' => 'required|min:8',
    ];
}

public function validateWithSymfony() {
    $validator = app(\Symfony\Component\Validator\ValidatorInterface::class);
    $data = $this->validate($this->rules());

    // Use Symfony for custom logic
    $user = new UserRegistration();
    $user->email = $data['email'];
    $user->password = $data['password'];

    $errors = $validator->validate($user, ['registration']);
    if ($errors->count() > 0) {
        throw new \Illuminate\Validation\ValidationException(
            $this->formatErrors($errors)
        );
    }
}

Validation in Console Commands

Validate CLI input using the same constraints:

use Symfony\Component\Validator\ValidatorInterface;

class ImportUsersCommand extends Command {
    protected $signature = 'users:import {file}';
    protected $description = 'Import users from a CSV file';

    public function handle(ValidatorInterface $validator) {
        $data = $this->getInputData();
        $user = (object) $data;

        $errors = $validator->validate($user);
        if ($errors->count() > 0) {
            $this->error('Validation failed: ' . implode(', ', $errors));
            return 1;
        }
        // Proceed with import
    }
}

Gotchas and Tips

Pitfalls

1. Dependency Conflicts

  • Issue: Symfony’s validator may conflict with Laravel’s dependencies (e.g., symfony/http-foundation).
  • Fix: Use composer.json overrides or pin versions:
    "extra": {
        "laravel": {
            "dont-discover": []
        }
    },
    "config": {
        "preferred-install": "dist",
        "sort-packages": true
    }
    
  • Run composer update carefully and test after updates.

2. Error Format Mismatch

  • Issue: Symfony’s ConstraintViolation objects don’t match Laravel’s ValidationException format.
  • Fix: Create a helper to transform errors:
    public function formatSymfonyErrors($errors) {
        return array_reduce($errors->toArray(), function ($carry, $error) {
            $carry[$error->getPropertyPath()][] = $error->getMessage();
            return $carry;
        }, []);
    }
    

3. Annotation Reading

  • Issue: Symfony’s annotation reader may not work out of the box in Laravel.
  • Fix: Ensure the validator builder enables annotation reading:
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor
spatie/laravel-javascript-views