Laravel 9, PHP 8.1. I had a form with two fields, start_date
and end_date
.
These fields were nullable, so either could be left blank to set an pen-ended start or end of the date range.
The dates needed to be validated to ensure the end date was after the start date,
and the start date was before the end date. But only when both are set.
The problem with applying the before
and after
validation rules is that if the field being compared
against is empty, then the validation rule always failed.
What was needed was for these rules to be injected only if needed, i.e. conditionally.
The when()
rule achieves this, and this gist shows how.
$rules = [
// ...
'start_date' => [
'nullable',
'date',
\Illuminate\Validation\Rule::when(
fn (\Illuminate\Support\Fluent $input) => $input->end_date ?? null,
fn () => 'before:end_date',
),
],
'end_date' => [
'nullable',
'date',
\Illuminate\Validation\Rule::when(
fn (\Illuminate\Support\Fluent $input) => $input->start_date ?? null,
fn () => 'after:start_date',
),
],
];
This is the logic that will be applied:
start_date | end_date | start_date validation | end_date validation |
---|---|---|---|
null | null | valid | valid |
any date | null | valid | valid |
null | any date | valid | valid |
low date | high date | valid | valid |
high date | low date | invalid | invalid |
I wanted to put the same validation on both start and end dates, so that if there is a validation error (the dates are in the wrong order) then both related form fields are highlighted with the appropriate error message.