asarray() 不影响事务本身,但返回数组无法调用 save();需用 activerecord 实例(如 findone)才能更新原记录并触发事件、保持事务一致性。

在 Yii2 事务中,asArray() 查询本身不会影响后续 save() 操作的执行或正确性,但它会影响你拿到的数据类型和后续操作的上下文——关键在于:你是否还持有可保存的 ActiveRecord 实例。
asArray() 返回的是纯数组,不是 AR 对象
调用 User::find()->asArray()->one() 或 ->all() 得到的是 PHP 关联数组(如 ['id' => 1, 'username' => 'admin']),它不继承 ActiveRecord,没有 save()、update()、事件钩子等方法。
- 你不能对这个数组直接调用
$row->save()—— 会报错 “Call to undefined method” - 即使你在事务里查出数组,再
new User()并赋值,那也是全新对象,跟原记录无关联,save()会插入新行而非更新原记录 - 若想更新原记录,必须用
User::findOne($id)获取 AR 实例,再修改属性并save()
对象查询(默认)天然支持 save 和事务一致性
像 User::findOne(1) 或 User::find()->where(['id' => 1])->one()(未加 asArray())返回的是 User 类实例,具备完整 AR 行为:
- 内部标记
isNewRecord = false,save()自动走 UPDATE - 触发
beforeSave、afterSave等生命周期事件 - 在事务中修改并
save(),其 SQL 会被包裹在当前事务内,回滚时一并撤销 - 能正确处理脏字段、时间戳自动填充、关联关系等
常见误用场景与建议
以下写法看似简洁,实则埋坑:
- ❌
$data = User::find()->asArray()->where(['id' => 1])->one(); $user = new User(); $user->setAttributes($data); $user->save();→ 插入新用户,非更新 - ❌ 在事务中先
asArray()查数据做判断,再手动拼 SQL 更新 → 绕过 AR 机制,丢失验证、事件、日志等能力 - ✅ 正确做法:需要更新就用 AR 实例;仅读取展示用
asArray()提升性能;混合场景下,先查 AR 实例用于操作,再用asArray()做只读渲染(如列表页) - ✅ 若必须从数组出发更新,可用
User::findOne($id)->load($array, '')或显式赋值后save(false)(跳过验证)
本质上,asArray() 是查询结果的格式选项,不改变事务行为,但切断了与 AR 模型能力的连接。是否能 save(),取决于你手里的变量是不是 ActiveRecord 实例,而不是事务有没有开启。











