Laravel избегает дублирования дат

Я новичок в Laravel и пытаюсь реализовать даты бронирования, которые не могут совпадать ни в какой день.

У меня есть модель под названием «Заказы», ​​которая включает room_id, start_date и end_date.

У меня есть проверка, которая проверяет, что дата окончания не может быть раньше начала:

$this->validate($request, [
        'start_date' => 'required|date',
        'end_date' => 'required|date|after_or_equal:start_date',
]);

Однако я не уверен, как проверить, что диапазон дат не конфликтует с другими диапазонами дат того же room_id, хранящегося в таблице бронирования (поскольку одна комната не может быть забронирована дважды в одном диапазоне).

Любая помощь будет оценена,

Спасибо!

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Laravel Scout - это популярный пакет, который предоставляет простой и удобный способ добавить полнотекстовый поиск в ваше приложение Laravel. Он...
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
3
0
2 413
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Есть встроенный углеродный метод isPast (), поэтому вы можете использовать:

$start_date->isPast()
$end_date->isPast()

Вы можете проверить, были ли оба выбранных объекта забронированы ранее.

Если вы не использовали Carbon, вот ссылка: https://carbon.nesbot.com/docs/

Ответ принят как подходящий

Вы должны проверить это в базе данных. Итак, вы можете сделать это:

$result = Bookings::where('start_date', '<=' $request->start_date)->where('end_date', '>=' $request->end_date)->where('room_id',$request->room_id)->first();
if (!$result){
  // Code to Book room
}

При типичном перекрытии, учитывая два события A и B, вы должны рассмотреть четыре сценария:

  1. Событие A содержит событие B
  2. Событие B содержит событие A
  3. Дата окончания события A совпадает с датой начала события B
  4. Дата окончания события B совпадает с датой начала события A

Итак, в sql, чтобы проверить, занята ли комната в интервале дат, скажем, 2018-11-20 'и' 2018-11-30 ', это будет:

select * 
from rooms 
where 
    start_date between '2018-11-20' and '2018-11-30' or 
    end_date between '2018-11-20' and '2018-11-30' or 
    '2018-11-20' between start_date and end_date or 
    '2018-11-30' between start_date and end_date;

В laravel я создаю область видимости в модели.

public function scopeByBusy($query,$start_date,$end_date) 
{ 
    return $query->whereBetween('start_date', [$start_date, $end_date]) 
        ->orWhereBetween('end_date', [$start_date, $end_date]) 
        ->orWhereRaw('? BETWEEN start_date and end_date', [$start_date]) 
        ->orWhereRaw('? BETWEEN start_date and end_date', [$end_date]); 
}

Наконец, я могу проверить, занята ли комната с идентификатором 95 в период между 2018-11-20 и 2018-11-30, вот так:

$room_id = 95;
$start = '2018-11-20';
$end = '2018-11-30';
$exists = Rooms::where('id', $room_id)
    ->byBusy($start, $end)
    ->first();

if ($exists)
{
    echo "the room is busy in the interval you selected";
}

Надеюсь, это вам поможет.

Очень хороший первый ответ. Я быстро просмотрел ваш пост и изменил форматирование на то, что обычно используется при переполнении стека. Также я исправил уязвимость SQL-инъекции во втором блоке кода. Вы можете использовать возможность построителей запросов для привязки параметров за вас, иначе запрос будет небезопасным. Но тем не менее хороший ответ!

Namoshek 26.11.2018 21:47

Спасибо @Namoshek. Я некоторое время играл с Laravel и другими вещами, но я так и не дал ответа, думаю, пришло время поделиться тем, что я узнал, с другими :). Спасибо, что поправили меня. Это хороший момент. Безопасность. Я не учел этого, потому что даты должны передавать запрос валидатора с правилами ['required', 'date_format: d / m / Y'] и даже использовать объект настраиваемого правила, чтобы проверить, что вторая дата больше или равно первой дате. Затем, когда даты попадают в контроллер, я форматирую их в формате базы данных «Y-m-d», затем я использую объем модели.

Juan Carlos Estrada Nieto 27.11.2018 22:29

Я немного опоздал, но нужен ли orWhereRaws? Думаю, достаточно двух условий. Последние - ненужные проверки.

glinda93 17.03.2020 18:40

У меня было аналогичное использование, когда мне нужно было проверить, запланировал ли человек что-то в диапазоне дат

Пример кода Laravel ниже:

 $start = Carbon::parse($request['start_date'])->format('Y-m-d 00:00:00');
 $end = Carbon::parse($request['end_date'])->format('Y-m-d 23:59:59');
 $existsActive = Microsite::where(function ($query) use ($start) {
                                      $query->where('start_date', '<=', $start);
                                      $query->where('end_date', '>=', $start);
                                  })->orWhere(function ($query) use ($end) {
                                      $query->where('start_date', '<=', $end);
                                      $query->where('end_date', '>=', $end);
                                  })->count();
 if ($existsActive > 0 ){
    echo "Already exists";  
 }

Я просто хотел проверить, есть ли у меня какие-либо перекрывающиеся записи в базе данных. Это сработало для меня.

Fawzan 31.07.2019 05:37

Другие вопросы по теме