J'essaie d'ajouter une condition en utilisant une requête JOIN avec 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')
);
Je sais que je peux utiliser expressions brutes mais alors il y aura des points d'injection SQL. J'ai essayé ce qui suit avec Query Builder mais la requête générée (et évidemment les résultats de la requête) ne correspond pas à ce que je voulais:
$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();
Voici la requête générée par 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
Comme vous pouvez le constater, la sortie de la requête n'a pas la structure (en particulier dans la portée JOIN). Est-il possible d'ajouter des conditions supplémentaires sous JOIN?
Comment puis-je construire la même requête en utilisant le générateur de requêtes de Laravel (si possible)? Est-il préférable d'utiliser Eloquent ou de rester avec DB :: select?
$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();
Pas tout à fait sûr si la clause between peut être ajoutée à la jointure dans laravel.
Notes:
DB::raw()
indique à Laravel de ne pas remettre les guillemets).on()
ajoutera AND
condition et orOn()
ajoutera OR
condition.Vous pouvez reproduire ces crochets dans la jointure de gauche:
LEFT JOIN bookings
ON rooms.id = bookings.room_type_id
AND ( bookings.arrival between ? and ?
OR bookings.departure between ? and ? )
est
->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(''));
})
Vous devrez ensuite définir les liaisons ultérieurement à l'aide de "setBindings" comme décrit dans ce SO post: Comment lier des paramètres à une requête de base de données brute dans Laravel utilisé sur un modèle?
Ce n'est pas joli mais ça marche.
Si vous avez des paramètres, vous pouvez le faire.
$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();
puis retournez votre requête
retourne $ résultats;
l'exemple de requête SQL comme celui-ci
LEFT JOIN bookings
ON rooms.id = bookings.room_type_id
AND (bookings.arrival = ?
OR bookings.departure = ?)
Laravel rejoindre avec plusieurs conditions
->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);
});
})
J'utilise laravel5.2 et nous pouvons ajouter des jointures avec différentes options que vous pouvez modifier selon vos besoins.
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();
Il y a une différence entre les requêtes brutes et les sélections standard (entre le DB::raw
et DB::select
méthodes).
Vous pouvez faire ce que vous voulez en utilisant un DB::select
et simplement déposer dans le ?
placeholder un peu comme vous le faites avec des déclarations préparées (c'est en fait ce que ça fait).
Un petit exemple:
$results = DB::select('SELECT * FROM user WHERE username=?', ['jason']);
Le deuxième paramètre est un tableau de valeurs qui seront utilisées pour remplacer les espaces réservés dans la requête de gauche à droite.