Подтвердить что ты не робот

СОЕДИНЕНИЕ с дополнительными условиями с использованием Query Builder или Eloquent

Я пытаюсь добавить условие, используя запрос JOIN с Laravel Query Builder.

<?php

$results = DB::select('
       SELECT DISTINCT 
          *
          FROM 
             rooms 
                LEFT JOIN bookings  
                   ON rooms.id = bookings.room_type_id
                  AND (  bookings.arrival between ? and ?
                      OR bookings.departure between ? and ? )
          WHERE
                bookings.room_type_id IS NULL
          LIMIT 20',
    array('2012-05-01', '2012-05-10', '2012-05-01', '2012-05-10')
);

Я знаю, что могу использовать необработанные выражения, но тогда будут точки внедрения SQL. Я попробовал следующее с Query Builder, но сгенерированный запрос (и, очевидно, результаты запроса) не то, что я хотел:

$results = DB::table('rooms')
    ->distinct()
    ->leftJoin('bookings', function ($join) {
        $join->on('rooms.id', '=', 'bookings.room_type_id');
    })
    ->whereBetween('arrival', array('2012-05-01', '2012-05-10'))
    ->whereBetween('departure', array('2012-05-01', '2012-05-10'))
    ->where('bookings.room_type_id', '=', null)
    ->get();

Это сгенерированный запрос от Laravel:

select distinct * from 'room_type_info'
    left join 'bookings' 
on 'room_type_info'.'id' = 'bookings'.'room_type_id' 
where 'arrival' between ? and ? 
    and 'departure' between ? and ? 
    and 'bookings'.'room_type_id' is null

Как видите, выходные данные запроса не имеют структуры (особенно в области JOIN). Можно ли добавить дополнительные условия в JOIN?

Как я могу построить тот же запрос, используя Laravel Query Builder (если это возможно). Лучше использовать Eloquent или оставить с DB :: select?

4b9b3361

Ответ 1

$results = DB::table('rooms')
                     ->distinct()
                     ->leftJoin('bookings', function($join)
                         {
                             $join->on('rooms.id', '=', 'bookings.room_type_id');
                             $join->on('arrival','>=',DB::raw("'2012-05-01'"));
                             $join->on('arrival','<=',DB::raw("'2012-05-10'"));
                             $join->on('departure','>=',DB::raw("'2012-05-01'"));
                             $join->on('departure','<=',DB::raw("'2012-05-10'"));
                         })
                     ->where('bookings.room_type_id', '=', NULL)
                     ->get();

Не совсем уверен, можно ли добавить условие промежуточного к соединению в laravel.

Заметки:

  • DB::raw() инструктирует Laravel не возвращать кавычки.
  • Передав закрытие методам соединения, вы можете добавить к нему больше условий соединения, on() добавит условие AND а orOn() добавит условие OR.

Ответ 2

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

LEFT JOIN bookings  
               ON rooms.id = bookings.room_type_id
              AND (  bookings.arrival between ? and ?
                  OR bookings.departure between ? and ? )

является

->leftJoin('bookings', function($join){
    $join->on('rooms.id', '=', 'bookings.room_type_id');
    $join->on(DB::raw('(  bookings.arrival between ? and ? OR bookings.departure between ? and ? )'), DB::raw(''), DB::raw(''));
})

Затем вам нужно будет установить привязки позже, используя "setBindings", как описано в этой записи SO: Как привязать параметры к необработанному запросу БД в Laravel, который используется на модели?

Это не очень, но это работает.

Ответ 3

Если у вас есть некоторые параметры, вы можете сделать это.

    $results = DB::table('rooms')
    ->distinct()
    ->leftJoin('bookings', function($join) use ($param1, $param2)
    {
        $join->on('rooms.id', '=', 'bookings.room_type_id');
        $join->on('arrival','=',DB::raw("'".$param1."'"));
        $join->on('arrival','=',DB::raw("'".$param2."'"));

    })
    ->where('bookings.room_type_id', '=', NULL)
    ->get();

а затем верните запрос

вернуть $results;

Ответ 4

Пример запроса SQL

LEFT JOIN bookings  
    ON rooms.id = bookings.room_type_id
    AND (bookings.arrival = ?
        OR bookings.departure = ?)

Laravel присоединиться к нескольким условиям

->leftJoin('bookings', function($join) use ($param1, $param2) {
    $join->on('rooms.id', '=', 'bookings.room_type_id');
    $join->on(function($query) use ($param1, $param2) {
        $query->on('bookings.arrival', '=', $param1);
        $query->orOn('departure', '=',$param2);
    });
})

Ответ 5

Я использую laravel5.2, и мы можем добавлять объединения с различными параметрами, вы можете изменять согласно вашему требованию.

Option 1:    
    DB::table('users')
            ->join('contacts', function ($join) {
                $join->on('users.id', '=', 'contacts.user_id')->orOn(...);//you add more joins here
            })// and you add more joins here
        ->get();

Option 2:
    $users = DB::table('users')
        ->join('contacts', 'users.id', '=', 'contacts.user_id')
        ->join('orders', 'users.id', '=', 'orders.user_id')// you may add more joins
        ->select('users.*', 'contacts.phone', 'orders.price')
        ->get();

option 3:
    $users = DB::table('users')
        ->leftJoin('posts', 'users.id', '=', 'posts.user_id')
        ->leftJoin('...', '...', '...', '...')// you may add more joins
        ->get();

Ответ 6

Существует разница между необработанными запросами и стандартными выборами (между методами DB::raw и DB::select).

Вы можете делать то, что хотите, с помощью DB::select и просто отбрасывать в заполнитель ? так же, как и с подготовленными операторами (это на самом деле то, что он делает).

Небольшой пример:

$results = DB::select('SELECT * FROM user WHERE username=?', ['jason']);

Второй параметр - это массив значений, который будет использоваться для замены заполнителей в запросе слева направо.