Description
Hi,
It's possible that when calling the getConstraint()
method on a ConstraintViolation
generated by the Assert\Collection
will return a different constraint than the Assert\Collection
that caused the violation.
An example:
$data = ['email' => 'some.email@domain.com'];
$constraints = new Assert\Collection([
'password' => new Assert\NotBlank(),
'email' => new Assert\NotBlank(),
]);
$violations = $->validate($data, $constraints);
dump($violations);
Outputs
Symfony\Component\Validator\ConstraintViolationList {#2675
-violations: array:1 [
0 => Symfony\Component\Validator\ConstraintViolation {#2677
-message: "This field is missing."
--- >8 ---
-constraint: Symfony\Component\Validator\Constraints\Collection { --- >8 --- }
-code: 1
}
]
}
This is the correct and expected behavior. The constraint within the ConstraintViolation
maps correctly to the constraint that caused the violation.
However, if we were to flip the order of field checks in the CollectionConstraint
like so:
$constraints = new Assert\Collection([
'email' => new Assert\NotBlank(),
'password' => new Assert\NotBlank(),
]);
The output will look like this
Symfony\Component\Validator\ConstraintViolationList {#2675
-violations: array:1 [
0 => Symfony\Component\Validator\ConstraintViolation {#2677
-message: "This field is missing."
--- >8 ---
-constraint: Symfony\Component\Validator\Constraints\NotBlank { --- >8 --- }
-code: 1
}
]
}
The constraint in the ConstraintViolation
is now mismatched from what the actual violation is.
Investigation
The reason this is happening is because of the way the context is passed into the validator when validating items in the Assert\Collection
.
Since the context is passed in, the constraint is modified on it and this change persists during the validation of the rest of the fields in the Collection constraint. So if a field is missing the violation created will be created with the same context that no longer references the Collection constraint.
Proposed solution
clone
ing the context in the inContext
call appears to fix the problem. I haven't dived in deep enough though to fully understand if there would be other side effects.