我一直在绞尽脑汁地思考一些没有返回所有应该包含的行的查询,我相信原因是绑定变量没有被正确地排序。这是一个流利的错误,还是我做错了什么?
这里有一个例子,赤裸裸的,展示了正在发生的事情。查询q1从具有简单where条件的表中选择。查询q2连接到表(某种程度),其中包含ON语句中的一个条件。主查询q连接到具有任意条件的表。
$q1 = DB::table('c')->where('d', '=', 'second');
$q2 = DB::table('e')->join('f', function($join){$join->where('f.id', '=', 'third');});
$q = DB::table('x')->join('y', function($join){$join->where('y.id', '=', 'first');})
->unionAll($q1) // binds to 'second'
->unionAll($q2); // binds to 'third'
var_dump($q->toSql());
var_dump($q->getBindings());当运行时,这是Fluent (在Laravel 4.2中)生成的查询和绑定数组:
(select * from `x` inner join `y` on `y`.`id` = ?)
union all
(select * from `c` where `d` = ?)
union all
(select * from `e` inner join `f` on `f`.`id` = ?)
array(3) {
[0]=>
string(2) "first"
[1]=>
string(2) "third"
[2]=>
string(2) "second"
}假设绑定变量按顺序匹配,从头到尾,第二次和第三次查询的绑定变量都是错误的,例如(select * fromcwhered= 'f1'),应该是(select * fromcwhered= 'd1').。
q1的where子句似乎被放在bind变量数组的末尾,而不管随后向联合添加了多少额外的查询。或者这就是这个简单的例子。也许绑定变量不应该按我认为应该的顺序排列?
Laravel将上述查询和绑定数组直接传递到PDO,无需进一步处理。
发布于 2014-09-26 10:15:32
对我的问题的回答是“是的”。Fluent是在UNION查询之间混合绑定变量,因此最终的bind变量数组的顺序是错误的。
Laravel查询生成器将查询的每个部分的绑定变量保存在一个数组中:
// Illuminate\Database\Query\Builder
protected $bindings = array(
'select' => [],
'join' => [],
'where' => [],
'having' => [],
'order' => [],
);通过这种方式,您可以按任意顺序构建查询--首先选择其中的位置,或者将其混合一些。对于单个查询来说,这是很好的。
然后,Laravel在构建联合时所做的就是将联合中每个查询中的这些数组合并在一起。这就是绑定变量混淆的地方。相反,它应该将每个查询的绑定变量数组解析为单个(线性)数组,然后按照连接联合查询的顺序将这些数组连接起来。
我把这当成一个虫子。我看不出一个简单的修复方法,所以使用了一个解决方案:分别运行每个查询,然后在PHP中合并结果,而不是期望数据库合并联合查询中的结果。其他解决方案,如手动将查询SQL和绑定连接在一起,并将它们直接传递给PDO,都是可行的,但我试图不重写Laravel中的逻辑。
https://github.com/laravel/framework/issues/5833
我的建议是,至少不要在拉拉维尔4.2使用工会。如果您的查询中没有任何绑定变量,那么您可能可以使用它。但是,请注意,查询生成器将对传递到查询的任何部分的任何字符串、数字、日期、数字或数组使用绑定变量。
https://stackoverflow.com/questions/26049541
复制相似问题