Как объединить запрос на 2 поля с условием ИЛИ? - PullRequest
0 голосов
/ 12 апреля 2020

В моем приложении laravel 5.8 мне нужно сделать отчет по таблице storage_spaces с 2 полями check_in_date и check_out_date при вводе года и месяца. Я делаю как:

$report_year = (int)$requestData['report_year'];
$report_month = (int)$requestData['report_month'];

$report_date_from= $report_year.'-'.$report_month.'-01';
if($report_month == 12) { // calculate from and till dates
    $report_month= 1;
    $report_year++;
} else {
    $report_month++;
}
$report_date_till= $report_year.'-'.$report_month.'-01';

$storageSpacesCollection = StorageSpace
    ...
    ->getByCheckInDate($report_date_from, ' >= ')
    ->getByCheckInDate($report_date_till, '< ')

    ->getByCheckOutDate($report_date_from, ' >= ')
    ->getByCheckOutDate($report_date_till, '< ')
    ...

В результате у меня неверный sql с несколькими условиями AND:

   SELECT `storage_spaces`.*, 
    FROM `storage_spaces` 
    ...
    WHERE storage_spaces.check_in_date  >= '2020-1-01'      AND storage_spaces.check_in_date < '2020-2-01'      AND storage_spaces.check_out_date  >= '2020-1-01'      AND storage_spaces.check_out_date < '2020-2-01'  
    ORDER BY `storage_spaces`.`id` asc 

Но ошибка в том, что между check_out_date и check_out_date должно быть условие OR, так как любая дата с датами начала / окончания должна быть в отчете.

Области определены в модели:

public function scopeGetByCheckInDate($query, $filter_check_in_date_from = null, string $sign = null)
{
    if ( ! empty($filter_check_in_date_from)) {
        if ( ! empty($sign)) {
            $query->whereRaw(DB::getTablePrefix().with(new StorageSpace)->getTable() . '.check_in_date ' . $sign . "'" . $filter_check_in_date_from . "' ");
        } else {
            $query->where(with(new StorageSpace)->getTable() . '.check_in_date', $filter_check_in_date_from);
        }
    }
    return $query;
}

public function scopeGetByCheckOutDate($query, $filter_check_out_date_from = null, string $sign = null)
{
    if ( ! empty($filter_check_out_date_from)) {
        if ( ! empty($sign)) {
            $query->whereRaw(DB::getTablePrefix().with(new StorageSpace)->getTable() . '.check_out_date ' . $sign . "'" . $filter_check_out_date_from . "' ");
        } else {
            $query->where(with(new StorageSpace)->getTable() . '.check_out_date', $filter_check_out_date_from);
        }
    }
    return $query;
}

Какой правильный способ установить условие ИЛИ?

ИЗМЕНЕННЫЙ БЛОК: с использованием группировки параметров (записано в https://laravel.com/docs/7.x/queries#parameter -группировка ) Я создал запрос:

$storageSpacesCollection = StorageSpace
    ::where(function ($query) use ($report_date_from, $report_date_till) {
        $query->whereRaw("storage_spaces.check_in_date >= '" . $report_date_from . "' ")
              ->whereRaw("storage_spaces.check_in_date < '" . $report_date_till . "' ") {

        $query->orWhereRaw("storage_spaces.check_out_date >= '" . $report_date_from . "' ")
              ->whereRaw("storage_spaces.check_out_date < '" . $report_date_till . "' ") // ERROR POINTS AT THIS LINE

        };
        }
    )
    ->orderBy('storage_spaces.id', 'asc')
    ->leftJoin('storage_capacities', 'storage_capacities.id', '=', 'storage_spaces.storage_capacity_id')
    ->leftJoin('warehouses', 'warehouses.id', '=', 'storage_spaces.warehouse_id')
    ->leftJoin('clients', 'clients.id', '=', 'storage_spaces.client_id')
    ->select(
        "storage_spaces.*",
        \DB::raw("CONCAT(storage_capacities.count, ' ', storage_capacities.sqft ) as storage_capacity_name"),
        "warehouses.name as warehouse_name",
        "clients.full_name as client_full_name"
    )
    ->get()

Но я получил ошибку:

Cannot use object of type Illuminate\Database\Eloquent\Builder as array

Какой синтаксис допустим?

Спасибо!

...