logo
podcast Podcast
get help Get Unstuck

Avoid overlapping date ranges with a familiar API

Feels like a built-in Laravel feature

Joel Clermont
Joel Clermont
2025-05-19

When your app stores date ranges (like a room reservation), you may need to ensure that no two records overlap.

There is nothing built in to Laravel that does this, but we can easily write a custom rule that checks the database for conflicts with existing records.

This works great when creating new date ranges, but you'll run into an issue during updates. Depending on the new values, the rule could see the record you’re editing as a collision with itself, so the validation fails when it shouldn't.

To solve this, we need to tell the rule to ignore the record being updated. We can add one method to our custom rule class:

public function ignore(?Reservation $reservation = null): self
{
    $this->ignore = $reservation;

    return $this;
}

And then we add a little bit of logic to our rule to honor that ignored record:

public function validate(string $attribute, mixed $value, Closure $fail): void
{
     $query = Reservation::where('starts_at', '<=', $value)
         ->where('ends_at', '>=', $value);

     if ($this->ignore) {
         $query->where($this->ignore->getKeyName(), '!=', $this->ignore->getKey());
     }

     if ($query->exists()) {
         $fail('validation.reservation_date_no_overlap')->translate();
     }
}

Not only does this work, and it's simple to implement, but I love that it mirrors how the built-in unique rule works.

In our rule, we chose to only ignore a model, whereas the built-in unique rule can also be passed the id for a model. It would be trivial to extend this to support that, but we didn't need it for our use case.

Here to help,

Joel

P.S. Aaron and I have thought a lot about validation rules. We captured our hard-earned knowledge in the Mastering Laravel Validation Rules book.

Toss a coin in the jar if you found this helpful.
Want a tip like this in your inbox every weekday? Sign up below 👇🏼
email
No spam. Only real-world advice you can use.