@EVOSandru6

Как вытащить модели с критерием по связи, а также не имеющим связи?

Добрый день,

Есть 2 модели:

Place (место для возможной аренды)
--id

и

Lease (аренда)
--id
--place_id
--started_at
--finished_at

Суть такая, что любой Place можно брать в аренду сколько угодно раз, главное чтобы это происходило не в период существующей аренды.

Хочу запросом вытащить все Place, которые:

1. В указанный период не находятся в стадии аренды.
2. Вообще ни разу не взятые в аренду.

Набросок:

public function search(Request $request)
    {

        $started_at = $request->query('started_at');
        $finished_at = $request->query('finished_at');

$places = Places::latest();

if(isset($started_at) && isset($finished_at)) {

            $places->whereHas('leases', function($q) use ($started_at, $finished_at) {
                $q
                    ->where('status', '<>', StatusesLeaseHelper::STATUS_WAIT)
                    ->where(function ($qq) use ($started_at, $finished_at) {

                        $qq->where(function ($qqq) use ($started_at, $finished_at) {
                            $qqq
                                ->where('started_at', '>', $started_at)
                                ->where('started_at', '>', $finished_at);

                        })->orWhere(function ($qqq) use ($started_at, $finished_at) {
                            $qqq
                                ->where('finished_at', '<', $started_at)
                                ->where('finished_at', '<', $finished_at);
                        });
                    });
            });
}

return $places->get();
 
}


Насколько я понимаю, данный фрагмент отвечает условию 1. т.к. затрагивается период к связи leases (модель Lease), но не учитываются places (пункт 2.), для которых не было ни одной аренды. Подскажите пожалуйста - как можно решить сей момент?
  • Вопрос задан
  • 119 просмотров
Решения вопроса 2
@alexalexes
Вам помогут классические запросы SQL?
Места, которые никогда не сдавались.
select distinct p.* from place p
left join lease l on p.id = l.place_id
where l.id is null -- нет записей в примыкаемой таблице lease, значит место не арендовалось

Места, которые никогда не сдавались, либо на рассматриваемый период свободны.
select distinct p.* from place p
left join lease l on p.id = l.place_id
where l.id is null
OR p.id not in (select distinct p.id -- находим арендованные места на период поиска
                  from place p
                  join lease l on p.id = l.place_id
                 where l.started_at >= :begin AND (l.finished_at is null OR l.finished_at <= :end) -- период аренды лежит внутри периода поиска
                    OR l.started_at <= :begin AND (l.finished_at is null OR l.finished_at >= :begin) -- точка начала периода поиска лежит в периоде аренды
                    OR l.started_at <= :end AND (l.finished_at is null OR l.finished_at >= :end) -- точка конца периода поиска лежит в периоде аренды
               )
Ответ написан
@vism
$places
->whereHas(....)
->orWhereNotExists(function ($query) {
                $query->select(DB::raw(1))
                      ->from('leases')
                      ->whereRaw('leases.place_id = places.id');
            })


Ну или еще проще добавить лефт джоин и проверять ->orWhereNull('leases.id')
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы