使用查询生成器或Eloquent进行具有附加条件的连接

我试图使用Laravel的查询构build器添加连接查询条件。

这是我试图用QB重写的查询:

$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 Ex [ressions( http://four.laravel.com/docs/queries#raw-expressions ),但是会有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范围下,是否可以在QB中join附加条件?)。

我如何使用Laravel的查询生成器(如果可能)构build相同的查询? 使用雄辩更好,还是应该留在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(); 

不太确定是否可以在laravel中添加between子句。

笔记:

  • DB :: raw()指示Laravel不要放回引号。
  • 通过传递一个闭包来连接方法,你可以添加更多的连接条件,on()会添加AND条件,orOn()会添加OR条件。

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

 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”来设置绑定,如本文所述: 如何将参数绑定到Laravel中用于模型的原始数据库查询?

这不是漂亮,但它的作品。

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

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

然后返回您的查询

返回$结果;

这样的SQL查询示例

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

Laraveljoin多个条件

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

我正在使用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(); 

原始查询和标准select(在DB::rawDB::select方法之间)是有区别的。

你可以用DB::select来做你想做的事, 占位符就像你准备好的语句一样(它实际上是在做什么)。

一个小例子:

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

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