yii2更新后我要重新获取ReportsProjects::updateAll($attributes, ['UUID' => $isCurrentReport->UUID]);或者刷新这个model
2026-03-03
这个问题本质是:
updateAll()是直接走 SQL,不会更新当前内存里的 model 实例。
所以你现在手里 $isCurrentReport 还是旧数据。
一、为什么会这样?
ReportsProjects::updateAll($attributes, ['UUID' => $uuid]);
这句是:
直接执行 UPDATE SQL
不触发 beforeSave / afterSave
不更新当前对象属性
不刷新 ActiveRecord 缓存
所以 $isCurrentReport 还是旧值。
二、正确做法(推荐三种)
✅ 方案一:刷新当前 model(最干净)
$isCurrentReport->refresh();
refresh() 会:
根据主键重新查询数据库
用最新数据覆盖当前对象
⚠ 前提:当前 model 必须有主键值。
✅ 方案二:重新查询(更保险)
$isCurrentReport = ReportsProjects::find() ->where(['UUID' => $isCurrentReport->UUID]) ->one();
适合:
你担心主键不是默认 id
UUID 是唯一键但不是主键
✅ 方案三:别用 updateAll,直接用 save(推荐做法)
如果你已经有 $isCurrentReport:
$isCurrentReport->attributes = $attributes; $isCurrentReport->save(false);
优点:
自动更新内存数据
触发 AR 事件
不需要 refresh
除非你批量更新,否则尽量不用 updateAll()。
三、批量更新后怎么刷新多个?
如果你 updateAll 更新了多条数据:
ReportsProjects::updateAll($attributes, $condition);
那就只能重新查:
$list = ReportsProjects::find() ->where($condition) ->all();
四、为什么很多人踩坑?
因为 updateAll:
不走 AR 层
不触发行为(behavior)
不更新时间戳(除非你自己传)
不触发 optimistic lock
它是“纯 SQL 快速通道”。
五、最安全建议(架构级建议)
如果不是极限性能场景:
✔ 用 $model->save()
✔ 少用 updateAll()
✔ 批量场景再用 updateAll
六、给你一个最佳实践写法(企业级)
$transaction = Yii::$app->db->beginTransaction();
try {
ReportsProjects::updateAll($attributes, ['UUID' => $uuid]);
$model = ReportsProjects::findOne(['UUID' => $uuid]);
$transaction->commit();
} catch (\Throwable $e) {
$transaction->rollBack();
throw $e;
}这样:
数据一致
状态最新
可控异常
如果你告诉我:
UUID 是不是主键?
你是单条更新还是批量?
有没有乐观锁字段?
我可以给你一版“更严谨的生产级写法”。
发表评论: