Skip to content

Commit c982ea5

Browse files
Allow to ignore specific nullable fields
1 parent 8174483 commit c982ea5

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
@@ -250,8 +250,9 @@ public function testValidateUniquenessWithNull(UniqueEntity $constraint)
250250

251251
/**
252252
* @dataProvider provideConstraintsWithIgnoreNullDisabled
253+
* @dataProvider provideConstraintsWithIgnoreNullEnabledOnFirstField
253254
*/
254-
public function testValidateUniquenessWithIgnoreNullDisabled(UniqueEntity $constraint)
255+
public function testValidateUniquenessWithIgnoreNullDisableOnSecondField(UniqueEntity $constraint)
255256
{
256257
$entity1 = new DoubleNameEntity(1, 'Foo', null);
257258
$entity2 = new DoubleNameEntity(2, 'Foo', null);
@@ -303,6 +304,7 @@ public function testAllConfiguredFieldsAreCheckedOfBeingMappedByDoctrineWithIgno
303304

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

342+
public function provideConstraintsWithIgnoreNullEnabledOnFirstField(): iterable
343+
{
344+
yield 'Doctrine style (name field)' => [new UniqueEntity([
345+
'message' => 'myMessage',
346+
'fields' => ['name', 'name2'],
347+
'em' => self::EM_NAME,
348+
'ignoreNull' => 'name',
349+
])];
350+
351+
yield 'Named arguments (name field)' => [new UniqueEntity(message: 'myMessage', fields: ['name', 'name2'], em: 'foo', ignoreNull: 'name')];
352+
}
353+
340354
public function testValidateUniquenessWithValidCustomErrorPath()
341355
{
342356
$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
@@ -85,7 +85,7 @@ public function validate(mixed $entity, Constraint $constraint)
8585
$class = $em->getClassMetadata($entity::class);
8686

8787
$criteria = [];
88-
$hasNullValue = false;
88+
$hasIgnorableNullValue = false;
8989

9090
foreach ($fields as $fieldName) {
9191
if (!$class->hasField($fieldName) && !$class->hasAssociation($fieldName)) {
@@ -94,11 +94,9 @@ public function validate(mixed $entity, Constraint $constraint)
9494

9595
$fieldValue = $class->reflFields[$fieldName]->getValue($entity);
9696

97-
if (null === $fieldValue) {
98-
$hasNullValue = true;
99-
}
97+
if (null === $fieldValue && $this->ignoreNullForField($constraint, $fieldName)) {
98+
$hasIgnorableNullValue = true;
10099

101-
if ($constraint->ignoreNull && null === $fieldValue) {
102100
continue;
103101
}
104102

@@ -114,7 +112,7 @@ public function validate(mixed $entity, Constraint $constraint)
114112
}
115113

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

@@ -193,6 +191,15 @@ public function validate(mixed $entity, Constraint $constraint)
193191
->addViolation();
194192
}
195193

194+
private function ignoreNullForField(UniqueEntity $constraint, string $fieldName): bool
195+
{
196+
if (\is_bool($constraint->ignoreNull)) {
197+
return $constraint->ignoreNull;
198+
}
199+
200+
return \in_array($fieldName, (array) $constraint->ignoreNull, true);
201+
}
202+
196203
private function formatWithIdentifiers(ObjectManager $em, ClassMetadata $class, mixed $value): string
197204
{
198205
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