Yii2逻辑歧义查询的解析规则及示例语句解读
Yii2链式查询条件的解析与逻辑规则
先看你给出的Yii2查询代码:
Product::find() ->where(['name' => 'MyProd']) ->andWhere(['type' => 'Toy']) ->orWhere(['category' => 'MyCat']) ->andWhere(['location' => 'MyLoc'])
正确的逻辑解析
这段代码最终生成的条件逻辑是:
位置等于'MyLoc',并且((名称等于'MyProd'且类型等于'Toy')或者分类等于'MyCat')
用SQL表达式表示就是:
WHERE ((name = 'MyProd' AND type = 'Toy') OR category = 'MyCat') AND location = 'MyLoc'
你的两种猜测都不准确:
- 第一种猜测((A AND B) OR (C AND D))不符合,因为最后一个
andWhere(['location' => 'MyLoc'])是和前面整个条件做AND,不是单独和orWhere的条件绑定 - 第二种猜测(A AND (B OR C) AND D)也不符合,因为
orWhere是和前面的(A AND B)做OR,不是和B单独做OR后再和A、D绑定
通用解析规则
Yii2查询构建器的链式条件遵循顺序组合、整体绑定的规则:
- 第一个
where()定义初始条件 - 后续的
andWhere($cond):将当前已构建的所有条件,与新条件$cond做AND运算(等价于把现有条件整体加括号,再和$cond用AND连接) - 后续的
orWhere($cond):将当前已构建的所有条件,与新条件$cond做OR运算(等价于把现有条件整体加括号,再和$cond用OR连接)
简单说,每一步的新条件都是和前面的整个条件集合组合,而不是和上一个单独的条件组合。
如何避免逻辑歧义
如果需要明确的分组逻辑,不要依赖链式调用的顺序,而是用嵌套数组手动定义逻辑结构:
- 要实现你的第一种猜测((A AND B) OR (C AND D)):
Product::find() ->where(['or', ['and', ['name' => 'MyProd'], ['type' => 'Toy']], ['and', ['category' => 'MyCat'], ['location' => 'MyLoc']] ])
- 要实现你的第二种猜测(A AND (B OR C) AND D):
Product::find() ->where(['name' => 'MyProd']) ->andWhere(['location' => 'MyLoc']) ->andWhere(['or', ['type' => 'Toy'], ['category' => 'MyCat']])
内容的提问来源于stack exchange,提问作者rosecabbagedragon
相关产品推荐
相关产品推荐

