Estou tentando adicionar uma condição usando uma consulta JOIN com o 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')
);
Sei que posso usar expressões brutas, mas haverá pontos de injeção de SQL. Tentei o seguinte com o Query Builder, mas a consulta gerada (e, obviamente, os resultados da consulta) não é o que eu pretendia:
$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();
Esta é a consulta gerada pelo 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
Como você pode ver, a saída da consulta não tem a estrutura (especialmente no escopo JOIN). É possível adicionar condições adicionais no JOIN?
Como posso construir a mesma consulta usando o Query Builder do Laravel (se possível) É melhor usar o Eloquent, ou deveria ficar com DB :: select?
and arrival >= ? and arrival <= ? and departure >= ? and departure <= ?
vezAND ( r.arrival between ? and ? OR r.departure between ? and ? )
(por favor observe aOR
cláusula). Isso adiciona linhas adicionais ao resultado que não deveriam estar lá. Eu acho que não é possível gerar todos os tipos de condições em join usando QB.Você pode replicar esses colchetes na junção à esquerda:
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('')); })
Você então terá que definir os vínculos mais tarde usando "setBindings" conforme descrito neste post do SO: Como vincular parâmetros a uma consulta de banco de dados bruta no Laravel que é usada em um modelo?
Não é bonito, mas funciona.
fonte
Se você tiver alguns parâmetros, pode fazer isso.
$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();
e depois retornar sua consulta
retornar $ resultados;
fonte
O exemplo de consulta sql como este
LEFT JOIN bookings ON rooms.id = bookings.room_type_id AND (bookings.arrival = ? OR bookings.departure = ?)
Laravel junta-se com múltiplas condições
->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); }); })
fonte
Estou usando o laravel5.2 e podemos adicionar associações com diferentes opções, que você pode modificar de acordo com sua necessidade.
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();
fonte
Há uma diferença entre as consultas brutas e as seleções padrão (entre os métodos
DB::raw
eDB::select
).Você pode fazer o que quiser usando um
DB::select
e simplesmente inserindo o?
espaço reservado, da mesma forma que faz com as instruções preparadas (na verdade, é o que está fazendo).Um pequeno exemplo:
$results = DB::select('SELECT * FROM user WHERE username=?', ['jason']);
O segundo parâmetro é uma matriz de valores que será usada para substituir os espaços reservados na consulta da esquerda para a direita.
fonte
$join->on('winners.year','=',DB::select('?',array('2013'));
mas não funcionou.