Laravel Eloquet/query Builder中LEFT JOIN的ON子句中的参数化查询绑定


Parameterized query binding in ON clause for a LEFT JOIN in Laravel Eloquent / Query Builder

假设我想显示type="color"的完整奖项列表:

Awards        Type     2013 Winner
======        ====     ===========
Blue Award    color       Tom
Red Award     color
Green Award   color       Dan  

为了实现这个结果,我可以在Laravel中进行如下查询:

$year = '2013';
$awards = DB::table('awards')
             ->leftJoin('winners', function($join) use ($year)
                   {
                        $join->on('awards.id','=','winners.award_id');
                        $join->on('winners.year','=',DB::raw("'".$year."'"));
                   }
             ->where('awards.type','color')
             ->get();

如果您输出Laravel生成的SQL,您将看到只有WHERE子句是参数化的,并且如果我从不受信任的源获取ON子句中的$year,则该子句容易受到SQL注入的攻击。此外,查询的缓存潜力也降低了,因为$year会经常更改注意:如果您认为我只是在查询的WHERE中添加第二个左联接条件,那么这两个条件就不一样了。

关于如何使查询的$year部分参数化,有什么想法吗?

这里有一个奇怪的解决方案(不想扩展Builder和JoinClause类):
注意:这将中断与->的查询链接,因此请注意where在下面是分开的

$query = DB::table('awards')
         ->leftJoin('winners', function($join)
               {
                    $join->on('awards.id','=','winners.award_id');
                    $join->on('winners.year','=',DB::raw('?'));  
               }
         ->setBindings(array_merge($query->getBindings(),array($year)));
$query->where('awards.type','color');
$awards = $query->get();

更新:Taylor添加了joinWhereleftJoinWhere。。。他说"如果你有一个函数join,只需要在闭包中使用->where->orWhere。"不过我还没有尝试过。

当前可以使用$join->where:

$year = '2013';
$awards = DB::table('awards')
         ->leftJoin('winners', 
               function($join) use ($year)
               {
                    $join
                        ->on('awards.id','=','winners.award_id')
                        // "where" instead of "on":
                        ->where('winners.year', '=', $year);
               }
         ->where('awards.type','color')
         ->get();

这直接来自Laravel文档:

Laravel查询生成器在整个过程中使用PDO参数绑定保护您的应用程序免受SQL注入攻击。有无需清理作为绑定传递的字符串。

你根本不需要消毒。应该没事。但是,如果您担心它,可以使用Validator类来验证它。