СОЕДИНЕНИЕ с дополнительными условиями с использованием 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?
Ответы
Ответ 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']);
Второй параметр - это массив значений, который будет использоваться для замены заполнителей в запросе слева направо.