Skip to content

Commit be7de29

Browse files
Allow to ignore specific nullable fields
1 parent db49c88 commit be7de29

File tree

3 files changed

+32
-9
lines changed

3 files changed

+32
-9
lines changed

src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,9 @@ public function testValidateUniquenessWithNull(UniqueEntity $constraint)
251251

252252
/**
253253
* @dataProvider provideConstraintsWithIgnoreNullDisabled
254+
* @dataProvider provideConstraintsWithIgnoreNullEnabledOnFirstField
254255
*/
255-
public function testValidateUniquenessWithIgnoreNullDisabled(UniqueEntity $constraint)
256+
public function testValidateUniquenessWithIgnoreNullDisableOnSecondField(UniqueEntity $constraint)
256257
{
257258
$entity1 = new DoubleNameEntity(1, 'Foo', null);
258259
$entity2 = new DoubleNameEntity(2, 'Foo', null);
@@ -304,6 +305,7 @@ public function testAllConfiguredFieldsAreCheckedOfBeingMappedByDoctrineWithIgno
304305

305306
/**
306307
* @dataProvider provideConstraintsWithIgnoreNullEnabled
308+
* @dataProvider provideConstraintsWithIgnoreNullEnabledOnFirstField
307309
*/
308310
public function testNoValidationIfFirstFieldIsNullAndNullValuesAreIgnored(UniqueEntity $constraint)
309311
{
@@ -338,6 +340,18 @@ public static function provideConstraintsWithIgnoreNullEnabled(): iterable
338340
yield 'Named arguments' => [new UniqueEntity(message: 'myMessage', fields: ['name', 'name2'], em: 'foo', ignoreNull: true)];
339341
}
340342

343+
public function provideConstraintsWithIgnoreNullEnabledOnFirstField(): iterable
344+
{
345+
yield 'Doctrine style (name field)' => [new UniqueEntity([
346+
'message' => 'myMessage',
347+
'fields' => ['name', 'name2'],
348+
'em' => self::EM_NAME,
349+
'ignoreNull' => 'name',
350+
])];
351+
352+
yield 'Named arguments (name field)' => [new UniqueEntity(message: 'myMessage', fields: ['name', 'name2'], em: 'foo', ignoreNull: 'name')];
353+
}
354+
341355
public function testValidateUniquenessWithValidCustomErrorPath()
342356
{
343357
$constraint = new UniqueEntity([

src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntity.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
* Constraint for the Unique Entity validator.
1818
*
1919
* @Annotation
20+
*
2021
* @Target({"CLASS", "ANNOTATION"})
2122
*
2223
* @author Benjamin Eberlei <kontakt@beberlei.de>
@@ -45,7 +46,8 @@ class UniqueEntity extends Constraint
4546
protected static $errorNames = self::ERROR_NAMES;
4647

4748
/**
48-
* @param array|string $fields the combination of fields that must contain unique values or a set of options
49+
* @param array|string $fields the combination of fields that must contain unique values or a set of options
50+
* @param bool|array|string $ignoreNull the combination of fields that ignore null values
4951
*/
5052
public function __construct(
5153
$fields,
@@ -55,7 +57,7 @@ public function __construct(
5557
string $entityClass = null,
5658
string $repositoryMethod = null,
5759
string $errorPath = null,
58-
bool $ignoreNull = null,
60+
bool|string|array $ignoreNull = null,
5961
array $groups = null,
6062
$payload = null,
6163
array $options = []

src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public function validate(mixed $entity, Constraint $constraint)
8787
$class = $em->getClassMetadata($entity::class);
8888

8989
$criteria = [];
90-
$hasNullValue = false;
90+
$hasIgnorableNullValue = false;
9191

9292
foreach ($fields as $fieldName) {
9393
if (!$class->hasField($fieldName) && !$class->hasAssociation($fieldName)) {
@@ -96,11 +96,9 @@ public function validate(mixed $entity, Constraint $constraint)
9696

9797
$fieldValue = $class->reflFields[$fieldName]->getValue($entity);
9898

99-
if (null === $fieldValue) {
100-
$hasNullValue = true;
101-
}
99+
if (null === $fieldValue && $this->ignoreNullForField($constraint, $fieldName)) {
100+
$hasIgnorableNullValue = true;
102101

103-
if ($constraint->ignoreNull && null === $fieldValue) {
104102
continue;
105103
}
106104

@@ -116,7 +114,7 @@ public function validate(mixed $entity, Constraint $constraint)
116114
}
117115

118116
// validation doesn't fail if one of the fields is null and if null values should be ignored
119-
if ($hasNullValue && $constraint->ignoreNull) {
117+
if ($hasIgnorableNullValue) {
120118
return;
121119
}
122120

@@ -195,6 +193,15 @@ public function validate(mixed $entity, Constraint $constraint)
195193
->addViolation();
196194
}
197195

196+
private function ignoreNullForField(UniqueEntity $constraint, string $fieldName): bool
197+
{
198+
if (\is_bool($constraint->ignoreNull)) {
199+
return $constraint->ignoreNull;
200+
}
201+
202+
return \in_array($fieldName, (array) $constraint->ignoreNull, true);
203+
}
204+
198205
private function formatWithIdentifiers(ObjectManager $em, ClassMetadata $class, mixed $value): string
199206
{
200207
if (!\is_object($value) || $value instanceof \DateTimeInterface) {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy