Skip to content
Advertisement

How beautifully to stop object property validation on the first error in Symfony?

I have the following code:


    class User
    {
        /**
         * @AssertType(type="string")
         * @AssertNotBlank()
         * @AssertEmail()
         * @AssertLength(max=255)
         */
        public $email;
    }

This object is filled from an API call. When validation takes place and property is filled with array value instead of string then NotBlank, Email, and Length validations continuing to work and I get “UnexpectedTypeException”.

I want validation system just to add one error about wrong value type and stop there.

I’ve made custom constraint validator


    class ChainConstraintValidator extends ConstraintValidator
    {
        /**
         * {@inheritdoc}
         */
        public function validate($value, Constraint $constraint)
        {
            if (!$constraint instanceof ChainConstraint) {
                throw new UnexpectedTypeException($constraint, __NAMESPACE__.'All');
            }

            $context = $this->context;
            $prevCount = $context->getViolations()->count();
            $validator = $context->getValidator()->inContext($context);

            foreach ($constraint->constraints as $constraintStep) {
                $errors = $validator->validate($value, $constraintStep);

                if ($errors->getViolations()->count() > $prevCount) {
                    break;
                }
            }
        }
    }

It works and I used it like this:


    @ChainConstraint(
        @AssertType(type="string"),
        @AssertNotBlank(),
        @AssertEmail(),
        @AssertLength(max=255)
    )
    

I have a lot of such classes in my project. Is there any more beautiful and requiring less code a way to achieve this?

Advertisement

Answer

What about this :

$var = [];

$constraints = [
 new Type(['type'=>'string', 'groups'=> 'first-check']),
 new NotBlank(['groups'=> 'second-check']),
 new Email(['groups'=> 'second-check']),
 new Length(['min'=>2, 'groups'=> 'second-check'])]
    ;

$groups = ['first-check', 'second-check'];
$groupSequence = new GroupSequence($groups);
$error = $validator->validate($var, $constraints, $groupSequence);

if(count($error) > 0) {
    dd($error); // Contains 1 ConstraintViolation (Type) 
 }
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement