Ich versuche, eine Bedingung mithilfe einer JOIN-Abfrage mit Laravel Query Builder hinzuzufügen.
<?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')
);
Ich weiß, dass ich Raw Expressions verwenden kann, aber dann wird es SQL-Injection-Punkte geben. Ich habe Folgendes mit dem Abfrage-Generator versucht, aber die generierte Abfrage (und natürlich die Abfrageergebnisse) entspricht nicht meinen Vorstellungen:
$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();
Dies ist die generierte Abfrage von 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
Wie Sie sehen, hat die Abfrage-Ausgabe nicht die Struktur (insbesondere im JOIN-Bereich). Können unter JOIN zusätzliche Bedingungen hinzugefügt werden?
Wie kann ich dieselbe Abfrage mit Laravels Query Builder erstellen (falls möglich)? Ist es besser, Eloquent zu verwenden, oder sollte ich bei DB :: select bleiben?
$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();
Nicht ganz sicher, ob die between-Klausel zum Join in laravel hinzugefügt werden kann.
Anmerkungen:
DB::raw()
weist Laravel an, keine Anführungszeichen zurückzusetzen.on()
fügt die AND
-Bedingung hinzu und orOn()
fügt die OR
-Bedingung hinzu.Sie können diese Klammern im linken Join replizieren:
LEFT JOIN bookings
ON rooms.id = bookings.room_type_id
AND ( bookings.arrival between ? and ?
OR bookings.departure between ? and ? )
ist
->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(''));
})
Sie müssen die Bindungen dann später mit "setBindings" festlegen, wie in diesem SO Beitrag beschrieben: So binden Sie Parameter an eine unformatierte DB-Abfrage in Laravel, das heißt Modell verwendet?
Es ist nicht schön, aber es funktioniert.
Wenn Sie einige Parameter haben, können Sie dies tun.
$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();
und geben Sie dann Ihre Anfrage zurück
$ results zurückgeben;
Das SQL-Abfragebeispiel wie dieses
LEFT JOIN bookings
ON rooms.id = bookings.room_type_id
AND (bookings.arrival = ?
OR bookings.departure = ?)
Laravel Join mit mehreren Bedingungen
->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);
});
})
Ich verwende laravel5.2 und wir können Verknüpfungen mit verschiedenen Optionen hinzufügen, die Sie gemäß Ihren Anforderungen ändern können.
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();
Es gibt einen Unterschied zwischen den unformatierten Abfragen und den Standardauswahlen (zwischen dem DB::raw
und DB::select
Methoden).
Sie können tun, was Sie wollen, indem Sie ein DB::select
und einfach in den ?
Platzhalter, ähnlich wie Sie es mit vorbereiteten Anweisungen tun (es ist eigentlich das, was es tut).
Ein kleines Beispiel:
$results = DB::select('SELECT * FROM user WHERE username=?', ['jason']);
Der zweite Parameter ist ein Array von Werten, mit denen die Platzhalter in der Abfrage von links nach rechts ersetzt werden.