Description
Symfony version(s) affected: 4.2.2
Description
Not sure whether this is a bug or the intended behaviour - but at least it seems to be inconsistent with my understanding on how null values are handled in the validator component.
Given two ?\DateTimeImmutable
properties (nullable) in a class to define a timespan where NULL
reflects unbounded, I'd like to use two comparison constraints to ensure that date 1 is always less than or equal to date 2. The AbstractComparisonValidator
however only deals with NULL
on the owning side of the constraint and does not handle NULL
on the propertyPath constraint leading to validation errors with the LessThanOrEqual
because the date 1 value (a \DateTimeImmutable
) is not less than or equal to NULL
. The GreaterThanOrEqual
constraint is no problem - by coincidence - because a \DateTimeImmutable
in date 2 is always greater than NULL
in date 1.
How to reproduce
use Symfony\Component\Validator\Constraints as Assert;
class UpdateValidity
{
/**
* @Assert\LessThanOrEqual(propertyPath="validUntil")
*
* @var \DateTimeImmutable|null
*/
public $validFrom;
/**
* @Assert\GreaterThanOrEqual(propertyPath="validFrom")
*
* @var \DateTimeImmutable|null
*/
public $validUntil;
}
$u = new UpdateValidity();
$u->validFrom = new \DateTimeImmutable('2019-01-01');
$u->validUntil = new \DateTimeImmutable('2019-12-31');
$validator->validate($u); // OK - validation succeeds
$u->validFrom = new \DateTimeImmutable('2020-01-01');
$validator->validate($u); // OK - validation fails
$u->validFrom = null;
$validator->validate($u); // OK - validation succeeds (by coincidence)
$u->validFrom = new \DateTimeImmutable('2019-01-01');
$u->validUntil = null;
$validator->validate($u); // Not OK - validation fails but should succeed in my opinion
Possible Solution
// vendor/symfony/validator/Constraints/AbstractComparisonValidator.php:50:62
if ($path = $constraint->propertyPath) {
if (null === $object = $this->context->getObject()) {
return;
}
try {
$comparedValue = $this->getPropertyAccessor()->getValue($object, $path);
} catch (NoSuchPropertyException $e) {
throw new ConstraintDefinitionException(sprintf('Invalid property path "%s" provided to "%s" constraint: %s', $path, \get_class($constraint), $e->getMessage()), 0, $e);
}
// <new>
if (null === $comparedValue) {
return;
}
// </new>
} else {
$comparedValue = $constraint->value;
}
Additional context
If required one could add a NotBlank
or NotNull
to the property to ensure that it must not be NULL
.