ПРИЄДНАЙТЕСЬ З додатковими умовами, використовуючи Конструктор запитів або Красномовний


93

Я намагаюся додати умову, використовуючи запит JOIN за допомогою 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')
);

Я знаю, що можу використовувати Raw Expressions, але тоді будуть точки введення SQL. Я спробував наступне за допомогою Query Builder, але згенерований запит (і, очевидно, результати запитів) не є тим, що я передбачав:

$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();

Це згенерований запит 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

Як бачите, вихідний запит не має структури (особливо в області JOIN). Чи можна додати додаткові умови в рамках ПРИЄДНАЙТЕСЯ?

Як я можу створити той самий запит, використовуючи Конструктор запитів Laravel (якщо це можливо). Чи краще використовувати Eloquent, чи слід залишатися з DB :: select?

Відповіді:


139
$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();

Не зовсім впевнений, чи може речення between бути додане до об'єднання в laravel.

Примітки:

  • DB::raw() доручає Ларавелю не відкладати цитати.
  • Передаючи методи закриття для приєднання, ви можете додати до нього більше умов приєднання, on()додасть ANDумову і orOn()додасть ORумову.

Дякую за відповідь. На жаль, згенерований запит дещо відрізняється, оскільки and arrival >= ? and arrival <= ? and departure >= ? and departure <= ?натомість тепер є умова об’єднання AND ( r.arrival between ? and ? OR r.departure between ? and ? )(зверніть увагу на ORпункт). Це додає додаткові рядки до результату, яких там не повинно бути. Думаю, неможливо створити всі типи умов для об’єднання за допомогою QB.
деде

1
Насправді я помітив, що? не додається до пропозицій ON. Ці значення в ON не параметризовані та не захищені від введення SQL. Я розмістив запитання, намагаючись з’ясувати рішення.
prograhammer

3
це не дало відповіді на початкове запитання, яке містило або пункт, який було проігноровано у цій відповіді.
ionescho

Ідеальне рішення. Тільки пам’ятайте використовувати DB :: raw при використанні значення, інакше Laravel (принаймні в 5.6.29) додає зворотні лапки і "розбиває" мету.
Адріан Ернандес-Лопес

35

Ви можете скопіювати ці дужки в лівому об’єднанні:

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(''));
})

Потім вам доведеться встановити прив'язки пізніше, використовуючи "setBindings", як описано в цій публікації SO: Як прив'язати параметри до необробленого запиту DB в Laravel, який використовується на моделі?

Це не красиво, але це працює.


32

Якщо у вас є параметри, ви можете це зробити.

    $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();

а потім поверніть свій запит

повернути $ результати;


23

Зразок запиту sql такий

LEFT JOIN bookings  
    ON rooms.id = bookings.room_type_id
    AND (bookings.arrival = ?
        OR bookings.departure = ?)

Laravel приєднується з декількома умовами

->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);
    });
})

11

Я використовую laravel5.2, і ми можемо додавати об’єднання з різними параметрами, ви можете змінити відповідно до ваших вимог.

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();

3

Існує різниця між необробленими запитами та стандартними виборами (між DB::rawіDB::select методами ).

Ви можете робити те, що хочете, використовуючи DB::selectі, просто занурюючи в ?заповнювач, подібно до того, як робите з підготовленими виписками (насправді це те, що він робить).

Невеликий приклад:

$results = DB::select('SELECT * FROM user WHERE username=?', ['jason']);

Другий параметр - це масив значень, який буде використовуватися для заміни заповнювачів у запиті зліва направо.


Чи означає це, що параметри автоматично захищаються (крім введення SQL)?
деде

2
Так, це просто обгортка для заяв, підготовлених PDO.
Джейсон Льюїс,

Чи є спосіб використовувати цю техніку в реченні ON у лівому об'єднанні? Дивіться моє запитання тут . Я намагався всередині мого лівого приєднання закрити, щоб зробити, $join->on('winners.year','=',DB::select('?',array('2013'));але не спрацював.
prograhammer

насправді це не так, наскільки красномовний призначений для роботи. Ви можете просто зробити DB :: raw () і зробити її самостійно
mydoglixu
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.