Estoy tratando de agregar una condición usando una consulta JOIN con 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')
);
Sé que puedo usar Raw Expressions, pero luego habrá puntos de inyección SQL. Probé lo siguiente con Query Builder, pero la consulta generada (y obviamente, los resultados de la consulta) no son lo que pretendía:
$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 es la consulta generada por 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 puede ver, la salida de la consulta no tiene la estructura (especialmente bajo el alcance JOIN). ¿Es posible agregar condiciones adicionales en JOIN?
¿Cómo puedo construir la misma consulta usando el Generador de consultas de Laravel (si es posible)? ¿Es mejor usar Eloquent, o debería quedarse con DB :: select?
and arrival >= ? and arrival <= ? and departure >= ? and departure <= ?
lugarAND ( r.arrival between ? and ? OR r.departure between ? and ? )
(observe laOR
cláusula). Esto agrega filas adicionales al resultado que no debería estar allí. Supongo que no es posible generar todos los tipos de condiciones en unir usando QB.Puede replicar esos corchetes en la combinación izquierda:
LEFT JOIN bookings ON rooms.id = bookings.room_type_id AND ( bookings.arrival between ? and ? OR bookings.departure between ? and ? )
es
->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('')); })
Luego, tendrá que configurar los enlaces más tarde usando "setBindings" como se describe en esta publicación SO: ¿Cómo enlazar parámetros a una consulta de base de datos sin procesar en Laravel que se usa en un modelo?
No es bonito pero funciona.
fuente
Si tiene algunos parámetros, puede hacer esto.
$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();
y luego devuelve tu consulta
devolver $ resultados;
fuente
La muestra de consulta SQL como esta
LEFT JOIN bookings ON rooms.id = bookings.room_type_id AND (bookings.arrival = ? OR bookings.departure = ?)
Laravel se une con múltiples condiciones
->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); }); })
fuente
Estoy usando laravel5.2 y podemos agregar uniones con diferentes opciones, puede modificar según sus requisitos.
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();
fuente
Hay una diferencia entre las consultas sin procesar y las selecciones estándar (entre los métodos
DB::raw
yDB::select
).Puede hacer lo que quiera usando un
DB::select
y simplemente colocando el?
marcador de posición como lo hace con las declaraciones preparadas (en realidad es lo que está haciendo).Un pequeño ejemplo:
$results = DB::select('SELECT * FROM user WHERE username=?', ['jason']);
El segundo parámetro es una matriz de valores que se utilizará para reemplazar los marcadores de posición en la consulta de izquierda a derecha.
fuente
$join->on('winners.year','=',DB::select('?',array('2013'));
pero no funcionó.