yii2中数组条件查询默认为and逻辑,支持键值对等值匹配及['operator','field',value]格式实现in、like等操作,null需显式写为null,避免sql注入。

Yii2 中用数组条件查询 ActiveRecord
Yii2 的 ActiveRecord 支持直接传入关联数组作为查询条件,这是最常用也最安全的方式。数组键是字段名,值是匹配内容,框架会自动参数化处理,避免 SQL 注入。
比如查 User 表中状态为 1 且类型为 'admin' 的记录:
$users = User::find()
->where(['status' => 1, 'type' => 'admin'])
->all();
注意:where() 接收的数组默认是「AND」逻辑;若需 OR,得显式用 ['or', ...] 结构,例如:
->where(['or', ['status' => 0], ['status' => 2]])
- 字符串字段建议用
trim()或数据库层面的TRIM()处理前后空格,数组条件本身不自动 trim - NULL 值匹配要写成
['field' => null],不是'field' => '',否则可能查不到空值记录 - 字段名别用驼峰(如
userName),除非已配置tableName()或启用驼峰转下划线映射
Yii2 数组条件里的操作符怎么写
纯键值对只能做等值匹配。要实现 IN、LIKE、BETWEEN 等,必须用带操作符的数组格式:['operator', 'field', value]。
常见写法:
// IN 查询 ->where(['in', 'id', [1, 2, 3]]) // LIKE(自动加 %) ->where(['like', 'name', 'john']) // 不区分大小写的 LIKE(MySQL 下生效) ->where(['ilike', 'email', 'gmail']) // 大于等于 ->where(['>=', 'created_at', '2024-01-01']) // BETWEEN ->where(['between', 'age', 18, 60])
-
like默认在前后加%,如需只前缀匹配,用['like', 'name', 'john', false]关闭自动补全 -
ilike在 PostgreSQL 中原生支持,在 MySQL 中会被转成LOWER()包裹,有性能影响 - 多个操作符嵌套时(如
['or', ['=', 'a', 1], ['in', 'b', [2,3]]]),括号层级要对齐,少一个中括号就报错
Yii3 里数组条件写法有变化吗
有。Yii3 的 Query 和 ActiveRecord 查询接口更严格,不再接受裸数组作为 where() 参数,默认只认 ExpressionInterface 或字符串条件。但可通过 yii\db\conditions\HashCondition 显式构造数组条件。
实际用法变成:
use yii\db\conditions\HashCondition; $query = User::find()->where(new HashCondition(['status' => 1]));
或者更常见的——直接用链式方法替代数组:
->andWhere(['=', 'status', 1]) ->andWhere(['=', 'type', 'admin'])
- Yii3 不再隐式识别
['in', ...]这类数组,必须用yii\db\conditions\InCondition等具体类 - 升级项目时,所有旧的数组条件调用都要检查,否则静默失效或抛出
InvalidConfigException - 如果混用 Yii2 和 Yii3 组件(比如只升级 DB 层),数组条件行为可能不一致,建议统一抽象层
数组条件和原生 SQL 混用容易出什么问题
当数组条件和字符串条件(如 'status = 1 AND name LIKE "%a%"')混用时,Yii 会把它们拼进同一 WHERE 子句,但参数绑定顺序可能错乱,导致 SQL 错误或查到意外数据。
典型翻车场景:
->where(['status' => 1])
->andWhere('name LIKE :pattern')
->addParams([':pattern' => '%test%'])
看起来没问题,但若前面的数组条件触发了内部参数重排(比如用了 in),:pattern 可能被覆盖或丢失绑定。
- 优先全部用数组条件,避免字符串拼接
- 真要混用,确保
addParams()在所有where()调用之后执行 - 调试时可用
$query->createCommand()->getRawSql()看最终 SQL,但注意它不显示参数值,得结合日志看绑定参数











