-
I have a DTO like this: #[TimeslotConsistency]
class TimeslotRequest
{
#[Assert\Sequentially([
new Assert\Type('string', message: 'request.value.invalid_type'),
new Assert\Date(message: 'request.value.invalid_date'),
])]
public $day;
#[Assert\Sequentially([
new Assert\NotBlank(message: 'request.value.not_blank'),
new Assert\Type('string', message: 'request.value.invalid_type'),
new Assert\Time(message: 'request.value.invalid_time', withSeconds: false),
])]
public $arrivalHour;
#[Assert\Sequentially([
new Assert\Type('float', message: 'request.value.invalid_type'),
])]
public $hours;
#[Assert\Sequentially([
new Assert\Type('string', message: 'request.value.invalid_type'),
new Assert\Time(withSeconds: false),
])]
public $departureHour;
} I have a class-level constraint ( class TimeslotConsistencyValidator extends ConstraintValidator
{
public function validate(mixed $value, Constraint $constraint): void
{
...
$arrivalDate = new DateTimeImmutable($value->getDay() . ' ' . $value->getArrivalHour());
$quantity = TimeslotDurationCalculator::calculateDurationInMinutes(
$arrivalDate,
$value->getHours(),
$value->getDepartureHour() ? new DateTimeImmutable($value->getDay() . ' ' . $value->getDepartureHour()) : null
);
...
}
} The problem is that this constraint is executed first, before the field-level constraints. So when I'm trying to instantiate the
My fix is updating the validator like this: try {
$arrivalDate = new DateTimeImmutable($value->getDay() . ' ' . $value->getArrivalHour());
$departureHour = $value->getDepartureHour() ? new DateTimeImmutable($value->getDay() . ' ' . $value->getDepartureHour()) : null;
} catch (\Throwable) {
// if the user submitted an invalid date/time, then we cannot proceed and must stop here to let the field-level constraint return the error.
return;
}
$quantity = TimeslotDurationCalculator::calculateDurationInMinutes(
$arrivalDate,
$value->getHours(),
$departureHour
); But I'd like to know if there is a way to execute the class-level constraint after the field-level ones? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
You can use a GroupSequence to first validate one group and then validate another one (and putting the class-level one constraint in the second group). Note however that validation does not stop at the first violation being reported. So your class-level constraint will still need to handle the case where field-level constraints have detected an invalid state. |
Beta Was this translation helpful? Give feedback.
You can use a GroupSequence to first validate one group and then validate another one (and putting the class-level one constraint in the second group).
Note however that validation does not stop at the first violation being reported. So your class-level constraint will still need to handle the case where field-level constraints have detected an invalid state.