it-swarm.com.de

A JOIN mit zusätzlichen Bedingungen mithilfe von Query Builder oder Eloquent

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?

66
dede
$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.
  • Indem Sie einen Abschluss an Join-Methoden übergeben, können Sie ihm weitere Join-Bedingungen hinzufügen. on() fügt die AND-Bedingung hinzu und orOn() fügt die OR-Bedingung hinzu.
97
Abishek

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.

32
rickywiens

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;

23
vroldan

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);
    });
})
13
Majbah Habib

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();
8
Abid Ali

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.

3
Jason Lewis