简体   繁体   English

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

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

Let's say I want to show a full list of awards with type="color": 假设我想显示一个完整的奖项列表,其中type =“color”:

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

To achieve this result I could have a query in Laravel like this: 为了达到这个结果,我可以在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();

If you output the SQL that Laravel generates you will see that only the WHERE clause is parameterized and $year in the ON clause is left vulnerable to sql injection if I get it from an untrusted source. 如果输出Laravel生成的SQL,您将看到只有WHERE子句被参数化,并且如果从不受信任的源获取它,则ON子句中的$ year容易受到sql注入的攻击。 Also the query's caching potential is reduced because $year will change often. 此外,查询的缓存潜力也会降低,因为$ year会经常更改。 Note : In case you were thinking that I just add the second left join condition to the WHERE of the query, these are not the same . 注意 :如果您认为我只是将第二个左连接条件添加到查询的WHERE,则这些不一样

Any ideas on how to get the $year part of the query parameterized? 有关如何获取查询的$ year部分的任何想法参数化?

Here's an odd work-around (didn't want to extend the Builder and JoinClause classes): 这是一个奇怪的解决方法(不想扩展Builder和JoinClause类):
Notice: This will break query chaining with -> so notice the where was seperated below. 注意:这将破坏查询链接与->所以注意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();

UPDATE : Taylor added joinWhere , leftJoinWhere ... he says that "if you have a function join just use ->where and ->orWhere from within the Closure." 更新泰勒添加了 joinWhereleftJoinWhere ...他说“如果你有一个函数连接只需使用->where->orWhere from the Closure。” I've yet to try this though. 我还没试过这个。

This comes straight from the Laravel docs: 这直接来自Laravel文档:

The Laravel query builder uses PDO parameter binding throughout to protect your application against SQL injection attacks. Laravel查询构建器始终使用PDO参数绑定来保护您的应用程序免受SQL注入攻击。 There is no need to clean strings being passed as bindings. 无需清除作为绑定传递的字符串。

You shouldn't need to sanitize it at all. 你根本不应该对它进行消毒。 It should be fine. 应该没问题。 If you are worried about it though, you can use the Validator class to validate it however you want. 如果你担心它,你可以使用Validator类来验证它。

Currently you can use $join->where : 目前你可以使用$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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM