laravel 使用查询生成器或Eloquent的带有附加条件的JOIN

368yc8dk  于 2023-06-24  发布在  其他
关注(0)|答案(9)|浏览(130)

我试图使用Laravel Query Builder中的JOIN查询添加一个条件。

<?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')
);

我知道我可以使用原始表达式,但这样就会有SQL注入点。我尝试了以下查询生成器,但生成的查询(显然,查询结果)不是我想要的:

$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作用域下)。是否可以在JOIN下添加附加条件?
如何使用Laravel的Query Builder构建相同的查询(如果可能的话)使用Eloquent更好,还是应该使用DB::select?

xlpyo6sf

xlpyo6sf1#

$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中的join中。

备注:

  • DB::raw()指示Laravel不要放回引号。
  • 通过向join方法传递闭包,你可以添加更多的join条件,on()将添加AND条件,orOn()将添加OR条件。
cwdobuhd

cwdobuhd2#

如果你有一些参数,你可以这样做。

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

然后返回您的查询
return $results;

wwwo4jvm

wwwo4jvm3#

你可以在左连接中复制这些括号:

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帖子所述:How to bind parameters to a raw DB query in Laravel that's used on a model?
虽然不好看但很管用。

disho6za

disho6za4#

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

x9ybnkn65#

我使用的是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();
t2a7ltrp

t2a7ltrp6#

对于条件参数,我们可以使用where

$results = DB::table('rooms')
             ->distinct()
             ->leftJoin('bookings', function($join) use ($param)
             {
                 $join->on('rooms.id', '=', 'bookings.room_type_id')
                      ->where('arrival','=', $param);
             })
             ->where('bookings.room_type_id', '=', NULL)
             ->get();
cwdobuhd

cwdobuhd7#

原始查询和标准选择之间存在差异(DB::rawDB::select方法之间)。
您可以使用DB::select来完成您想要的操作,只需添加?占位符,就像使用预准备语句一样(这实际上就是它正在做的事情)。
举个小例子:

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

第二个参数是一个值数组,将用于从左到右替换查询中的占位符。

k5ifujac

k5ifujac8#

我的五美分计划左加入(..或)和(..或..)和..

->join('checks','checks.id','check_id')
    ->leftJoin('schema_risks', function (JoinClause $join) use($order_type_id, $check_group_id,  $filial_id){
        $join->on(function($join){
            $join->on('schema_risks.check_method_id','=', 'check_id')
                ->orWhereNull('schema_risks.check_method_id')
                ;
        })
        ->on(function($join) use ($order_type_id) {
            $join->where('schema_risks.order_type_id', $order_type_id)
                ->orWhereNull('schema_risks.order_type_id')
                ;
        })
        ->on(function($join) use ($check_group_id) {
            $join->where('schema_risks.check_group_id', $check_group_id)
                ->orWhereNull('schema_risks.check_group_id')
                ;
        })
        ->on(function($join) use($filial_id){
            $join->whereNull('schema_risks.filial_id');
            if ($filial_id){
                $join->orWhere('schema_risks.filial_id', $filial_id);
            }
        })            
        ->on(function($join){
            $join->whereNull('schema_risks.check_risk_level_id')
                ->orWhere('schema_risks.check_risk_level_id', '>' , CheckRiskLevel::CRL_NORMALLLY );
        })
        ;
    })
u4dcyp6a

u4dcyp6a9#

新版本提示:

$rooms = Room::select('rooms.*', 'bookings.type3')
        ->join('bookings', function (JoinClause $join) {
            $join->on(['bookings.cat1' => 'rooms.cat1', 'bookings.cat2' => 'rooms.cat2']);
        })->get();;

除了使用两个on-condition(AND-Conditions),您还可以在其所有函数中使用orOn()-Conditions,as Between,...

相关问题