Closed
Description
Symfony version(s) affected
6.4
Description
When I make nested constraints AtLeastOneOf, the validator will skip all violations.
The Symfony validator employs two factories for initializing an instance of a constraint validator:
- Symfony\Component\ValidatorConstraintValidatorFactory - creates a new instance of the validator and caches it as an array.
- Symfony\Component\ContainerConstraintValidatorFactory - retrieves the validator from the DI container. As each unique service in a container is passed by reference, each validator is initialized only once.
The issue arises when creating a nested constraint, such as AtLeastOneOf
. At line 752 of RecursiveContextualValidator
, a new context for this validator is initialized, which is the root cause of the bug.
How to reproduce
To reproduce this bug, you can use the following code:
<?php
declare(strict_types=1);
use Symfony\Component\Validator\Constraints\AtLeastOneOf;
use Symfony\Component\Validator\Constraints\Choice;
use Symfony\Component\Validator\Constraints\Collection;
use Symfony\Component\Validator\Constraints\Type;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Validation;
require_once dirname(__DIR__) . '/vendor/autoload.php';
$values = [
'AtLeastOneOf' => [
'field1' => 'test',
'AtLeastOneOfNested1' => [
'AtLeastOneOfNested2' => \uniqid(),
'field2' => \uniqid(),
],
],
'test2' => '1',
];
$constraints = new Collection([
'AtLeastOneOf' => new AtLeastOneOf([
new Collection([
'field1' => new NotBlank(),
'AtLeastOneOfNested1' => new AtLeastOneOf([
new Collection([
'AtLeastOneOfNested2' => new AtLeastOneOf([
new Type('int'),
new Choice(['test1', 'test2'])
]),
]),
new Collection([
'field2' => new Type('int'),
]),
]),
]),
new Collection([
'field3' => new NotBlank(),
'AtLeastOneOfNested3' => new AtLeastOneOf([
new Collection([
'field1' => new Type('int'),
]),
new Collection([
'field2' => new Type('int'),
]),
]),
]),
]),
'test2' => new NotBlank(),
]);
$violations = Validation::createValidator()->validate($values, $constraints);
echo $violations->count() . \PHP_EOL;
As we can see, incorrect data exists for the key AtLeastOneOfNested1
, but the validator skips these violations.
Possible Solution
A possible solution is to consistently initialize a new instance of AtLeastOneOfValidator
within a factory.
Additional Context
No response