8000 bug #54137 [Validator] UniqueValidator - normalize before reducing ke… · symfony/symfony@04652b7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 04652b7

Browse files
committed
bug #54137 [Validator] UniqueValidator - normalize before reducing keys (Brajk19)
This PR was squashed before being merged into the 6.4 branch. Discussion ---------- [Validator] UniqueValidator - normalize before reducing keys | Q | A | ------------- | --- | Branch? | 6.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Issues | | License | MIT In #42403 checking for uniqueness of certain collection keys was enabled. Method `UniqueValidator::reduceElementKeys` removes all keys which are not specified. Problem is that this happens before normalization, which in my opinion is not great because that method accepts array argument and if i have some object (DTO), TypeError will be thrown. Example: ```php class ParentDTO { /** * `@var` ChildDTO[] */ #[Assert\Unique( normalizer: [ChildDTO::class, 'normalize'] fields: 'id' )] public array $children; } ``` ```php class ChildDTO { public string $id; public string $name; public static function normalize(self $obj): array { return [ 'id' => $obj->id, 'name' => $obj->name ]; } } ``` Because normalization will happen after `reduceElementKeys` this will be thrown: `TypeError: Symfony\Component\Validator\Constraints\UniqueValidator::reduceElementKeys(): Argument #2 ($element) must be of type array, ...\ChildDTO given, called in .../UniqueValidator.php on line 48` If `$element = $normalizer($element);` is executed before `reduceElementKeys` it would enable using Assert\Unique with array of objects when correctly normalized Commits ------- 77df90b [Validator] UniqueValidator - normalize before reducing keys
2 parents 5dbc82d + 77df90b commit 04652b7

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

src/Symfony/Component/Validator/Constraints/UniqueValidator.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ public function validate(mixed $value, Constraint $constraint)
4343
$collectionElements = [];
4444
$normalizer = $this->getNormalizer($constraint);
4545
foreach ($value as $element) {
46+
$element = $normalizer($element);
47+
4648
if ($fields && !$element = $this->reduceElementKeys($fields, $element)) {
4749
continue;
4850
}
4951

50-
$element = $normalizer($element);
51-
5252
if (\in_array($element, $collectionElements, true)) {
5353
$this->context->buildViolation($constraint->message)
5454
->setParameter('{{ value }}', $this->formatValue($value))

src/Symfony/Component/Validator/Tests/Constraints/UniqueValidatorTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
1717
use Symfony\Component\Validator\Exception\UnexpectedValueException;
1818
use Symfony\Component\Validator\Test\ConstraintValidatorTestCase;
19+
use Symfony\Component\Validator\Tests\Dummy\DummyClassOne;
1920

2021
class UniqueValidatorTest extends ConstraintValidatorTestCase
2122
{
@@ -283,6 +284,36 @@ public static function getInvalidCollectionValues(): array
283284
],
284285
];
285286
}
287+
288+
public function testArrayOfObjectsUnique()
289+
{
290+
$array = [
291+
new DummyClassOne(),
292+
new DummyClassOne(),
293+
new DummyClassOne(),
294+
];
295+
296+
$array[0]->code = '1';
297+
$array[1]->code = '2';
298+
$array[2]->code = '3';
299+
300+
$this->validator->validate(
301+
$array,
302+
new Unique(
303+
normalizer: [self::class, 'normalizeDummyClassOne'],
304+
fields: 'code'
305+
)
306+
);
307+
308+
$this->assertNoViolation();
309+
}
310+
311+
public static function normalizeDummyClassOne(DummyClassOne $obj): array
312+
{
313+
return [
314+
'code' => $obj->code,
315+
];
316+
}
286317
}
287318

288319
class CallableClass

0 commit comments

Comments
 (0)
0