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

symfony/validator

Symfony Validator provides a flexible validation system based on the JSR-303/Bean Validation model. Define constraints via annotations/attributes, YAML/XML, or PHP, validate objects and values, and get detailed, localized violation messages.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

  1. Installation:

    composer require symfony/validator
    

    Laravel already includes this package via Symfony components, so no additional configuration is needed.

  2. First Use Case: Validate a request payload in a Laravel controller:

    use Symfony\Component\Validator\Validator\ValidatorInterface;
    use Symfony\Component\Validator\Constraints as Assert;
    
    public function store(Request $request, ValidatorInterface $validator)
    {
        $data = $request->validate([
            'email' => ['required', 'email'],
            'age' => ['integer', 'min' => 18, 'max' => 120],
        ]);
    
        // Manual validation (alternative to Laravel's built-in)
        $errors = $validator->validate($data, [
            new Assert\Email(),
            new Assert\GreaterThanOrEqual(18),
            new Assert\LessThanOrEqual(120),
        ]);
    
        if (count($errors) > 0) {
            return response()->json(['errors' => (string) $errors], 400);
        }
    
        // Proceed with logic...
    }
    
  3. Where to Look First:

    • Symfony Validator Documentation
    • Laravel’s built-in Request::validate() (which uses Symfony Validator under the hood)
    • ValidatorInterface for programmatic validation.

Implementation Patterns

1. Form Request Validation

Extend Laravel’s FormRequest and leverage Symfony’s constraints:

use Illuminate\Foundation\Http\FormRequest;
use Symfony\Component\Validator\Constraints as Assert;

class StoreUserRequest extends FormRequest
{
    public function rules()
    {
        return [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'email', 'unique:users'],
        ];
    }

    public function withValidator($validator)
    {
        $validator->addConstraintTo('email', new Assert\NotBlank());
        $validator->addConstraintTo('age', new Assert\Type('integer'));
    }
}

2. Custom Constraints

Create reusable validation rules:

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

class UniqueUsername 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();
        }
    }
}

Usage:

$validator->validate($data, [
    new UniqueUsername(),
]);

3. Grouped Validation

Validate subsets of data:

use Symfony\Component\Validator\Constraints\GroupSequence;

$validator->validate($data, new GroupSequence([
    'Default',
    'createUser',
]));

Define groups in your DTO:

use Symfony\Component\Validator\Constraints as Assert;

class UserDto
{
    #[Assert\NotBlank(groups: ['createUser'])]
    public string $password;

    #[Assert\Email(groups: ['Default'])]
    public string $email;
}

4. Validation in Services

Inject ValidatorInterface into services:

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

    public function create(array $data): void
    {
        $errors = $this->validator->validate($data, [
            new Assert\All([
                new Assert\Type('string'),
                new Assert\NotBlank(),
            ]),
        ]);

        if ($errors->count() > 0) {
            throw new \InvalidArgumentException((string) $errors);
        }
    }
}

5. API Response Handling

Format validation errors for JSON APIs:

public function validateAndRespond(Request $request, ValidatorInterface $validator)
{
    $data = $request->all();
    $errors = $validator->validate($data, [
        new Assert\Collection([
            'email' => [new Assert\Email()],
            'age' => [new Assert\Range(['min' => 18])],
        ]),
    ]);

    if ($errors->count() > 0) {
        return response()->json([
            'errors' => array_map(function ($error) {
                return $error->getPropertyPath() . ': ' . $error->getMessage();
            }, iterator_to_array($errors)),
        ], 422);
    }
}

6. Dynamic Constraints

Use closures for runtime validation:

use Symfony\Component\Validator\Expression;

$validator->validate($data, [
    new Assert\Expression(
        'value > 10',
        ['value' => $data['value']],
        'Value must be greater than 10.'
    ),
]);

7. Laravel Integration Tips

  • Use Laravel’s Validator facade (wraps Symfony’s ValidatorInterface):
    use Illuminate\Support\Facades\Validator;
    
    $validator = Validator::make($data, [
        'email' => 'required|email',
    ]);
    
  • Custom Rule Objects:
    use Illuminate\Contracts\Validation\Rule;
    
    class UniqueUsernameRule implements Rule
    {
        public function passes($attribute, $value)
        {
            return !User::where('username', $value)->exists();
        }
    
        public function message()
        {
            return 'The :attribute is already taken.';
        }
    }
    
    Usage in Laravel:
    $validator->addRules([
        'username' => ['required', new UniqueUsernameRule],
    ]);
    

Gotchas and Tips

Pitfalls

  1. Constraint Order Matters:

    • Constraints are evaluated in the order they are defined. Place stricter constraints (e.g., NotBlank) before broader ones (e.g., Type).
  2. Circular References:

    • Validating objects with circular references (e.g., User hasMany Posts, Post belongsTo User) can cause infinite loops. Use ValidationContext::disableOriginalValueNormalization() or lazy-loading.
  3. Lazy-Loading Properties:

    • Accessing lazy-loaded properties (e.g., Eloquent relations) during validation triggers queries. Use ValidationContext::disableOriginalValueNormalization() or load relations beforehand:
      $user->load('posts');
      $validator->validate($user);
      
  4. Nested Arrays/Objects:

    • Symfony Validator does not recursively validate nested arrays/objects by default. Use Assert\Collection or Assert\All:
      new Assert\Collection([
          'field' => new Assert\All([
              new Assert\Type('string'),
          ]),
      ]);
      
  5. Custom Constraint Caching:

    • Symfony caches constraint metadata. Clear cache when adding new constraints dynamically:
      $validator->getMetadataFactory()->clearCache();
      
  6. Deprecations in Symfony 8+:

    • Avoid implicit constraint options in YAML/XML (use explicit keys).
    • GroupSequence no longer accepts associative arrays (use indexed arrays or GroupSequenceProvider).
  7. Performance with Large Datasets:

    • Validating large arrays/objects can be slow. Use ValidationContext::disableOriginalValueNormalization() or validate subsets.

Debugging Tips

  1. Inspect Violations:

    $errors = $validator->validate($data);
    foreach ($errors as $error) {
        dump([
            'property' => $error->getPropertyPath(),
            'message' => $error->getMessage(),
            'code' => $error->getCode(),
        ]);
    }
    
  2. Enable Validation Groups:

    • Use groups to isolate validation logic:
      new Assert\NotBlank(groups: ['registration']),
      
  3. Constraint Violation Codes:

    • Access specific error codes for granular handling:
      $errors->findByCodes(['unique']);
      
  4. Disable Normalization:

    • Skip normalization (e.g., for complex objects):
      $validator->validate($data, [], null, [
          'disableOriginalValueNormalization' => true,
      ]);
      

Extension Points

  1. Custom Constraint Validators:

    • Extend ConstraintValidator for complex logic:
      class CustomValidator extends ConstraintValidator
      {
          protected function validateCustom($value, Constraint $constraint)
          {
              if (!preg_match($constraint->pattern, $value)) {
                  $this->context->buildViolation($constraint->message)
                      ->addViolation();
              }
          }
      }
      
  2. Validation Context:

    • Access the validation context for dynamic behavior:
      $context = $this->context;
      $root = $context->getRoot();
      
  3. Constraint Compilation:

    • Override constraint compilation for performance:
      $metadataFactory = new MetadataFactory();
      $metadataFactory->setMetadataCache(new FileCache(sys_get_temp_dir()));
      $validator = new Validator($metadataFactory);
      
  4. Laravel Service Provider:

    • Bind custom validators in `
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.
croct/coding-standard
croct/plug-php
nqxcode/phpmorphy
boundwize/pyrameter
testo/facade
develia/commons
dmstr/symfony-system-resources-bundle
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
renatomarinho/laravel-page-speed
develia/geo-bundle
austinheap/laravel-database-encryption
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
imbo/imbo-coding-standard
visualbuilder/filament-lottie
servicioslineaonce/starter-kit
atomcoder/laravel-reorderable
irajul/filament-shadcn-theme