You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Yii2查询中使用复杂表达式?附SQL示例

嘿,刚好对Yii2的查询构建这块熟得很,来给你掰扯清楚where()里能塞啥,尤其是你提到的这种位运算复杂表达式的场景~

Yii2 Query 中where()的可用表达式类型

1. 直接传入SQL字符串(适配你的需求场景)

你要实现的SELECT * FROM a WHERE a & 1 = a,直接把条件字符串丢进where()就行,非常直接:

$models = YourModel::find()
    ->where('a & 1 = a')
    ->all();

⚠️ 划重点:如果条件里要用到变量,绝对不能直接字符串拼接,一定要用参数绑定防SQL注入,比如:

$bitMask = 1;
$models = YourModel::find()
    ->where('a & :mask = a', [':mask' => $bitMask])
    ->all();

2. 数组格式(推荐,更安全、易维护)

Yii2支持多种数组式条件写法,能覆盖绝大多数场景,包括复杂运算:

简单键值对(等价AND条件)

适合多个相等判断的场景:

// 等价于 WHERE `id` = 1 AND `status` = 'active'
->where(['id' => 1, 'status' => 'active'])

操作符数组(处理非相等的复杂运算)

对于位运算这类特殊操作,用['操作符', '列名', 表达式/值]的格式,配合Expression来实现:

// 等价于 WHERE (a & 1) = a
->where(['=', new \yii\db\Expression('a & 1'), 'a'])

逻辑组合数组(混合AND/OR)

可以把不同类型的条件组合起来,非常灵活:

// 等价于 WHERE (a & 1 = a) AND (status = 'active') AND (created_at > '7天前的时间戳')
->where([
    'AND',
    'a & 1 = a',
    ['status' => 'active'],
    ['>', 'created_at', strtotime('-7 days')]
])

3. 使用yii\db\Expression处理复杂SQL片段

如果你的条件里包含SQL函数、位运算、自定义表达式,Expression是最优解——它会原样输出你写的SQL,不会被Yii2的查询构建器转义:

// 无参数的复杂表达式
$expr = new \yii\db\Expression('a & 1 = a');
$models = YourModel::find()->where($expr)->all();

// 带参数的版本(依然防注入)
$expr = new \yii\db\Expression('a & :mask = a', [':mask' => 1]);
$models = YourModel::find()->where($expr)->all();

4. 其他进阶用法

  • 子查询作为条件:
$subQuery = OtherModel::find()->select('id')->where(['status' => 1]);
// 等价于 WHERE a_id IN (SELECT id FROM other_table WHERE status = 1)
->where(['in', 'a_id', $subQuery])
  • 范围类条件:
// WHERE id BETWEEN 1 AND 10
->where(['between', 'id', 1, 10])
// WHERE id IN (1, 3, 5)
->where(['in', 'id', [1, 3, 5]])
// WHERE id NOT IN (2, 4)
->where(['not in', 'id', [2, 4]])

总的来说,简单条件用数组格式最省心,复杂的自定义SQL直接用字符串或者Expression,记得所有外部变量都要绑定参数,别碰SQL注入的坑~

内容的提问来源于stack exchange,提问作者Bryan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:53:45