无尘阁日记

无尘阁日记

yii2 的AR的refresh可以让模型刷新到最新吧?就是刚刚更新过的
2026-03-05

大方向是对的,但有一个很关键的小细节很多人容易误解。我把 Yii2 里 ActiveRecord::refresh() 的真实行为给你讲清楚。

一、refresh() 的作用是什么

在 Yii2 中:

$model->refresh();

作用是:

从数据库重新读取当前记录的数据,并覆盖当前模型对象的属性。

也就是说:

数据库 → 重新加载 → 覆盖当前AR对象

官方行为可以理解为:

重新执行一次 SELECT

相当于:

SELECT * FROM table WHERE primary_key = ?

二、典型使用场景

例如:

$user = User::findOne(1);

$user->name = 'A';
$user->save();

$user->refresh();

执行流程:

save() → 更新数据库
refresh() → 再从数据库读取

这样 $user 里的属性就是 数据库最新状态

三、refresh() 为什么有用

很多情况下数据库的数据会被 别的逻辑修改

例如:

1 数据库触发器

update_time 自动更新

2 数据库默认值

created_at = NOW()

3 其他进程修改

例如:

队列
定时任务
其他接口

这时:

$model->refresh();

就能把最新值同步回来。

四、refresh() 会做什么操作

refresh 会做三件事:

1 重新查询数据库

$this->findOne($this->primaryKey)

2 覆盖当前属性

$this->attributes = db_attributes

3 清空 dirtyAttributes

所以 refresh 后:

模型状态 = 干净

五、refresh() 不会做什么

refresh 不会重新创建对象

还是原来的 $model

只是:

覆盖属性

六、refresh() 的返回值

if ($model->refresh()) {
}

返回:

true  成功
false 记录不存在

例如记录被删了。

七、refresh 的源码逻辑(简化版)

核心逻辑其实很简单:

public function refresh()
{
    $record = static::findOne($this->getPrimaryKey());
    
    if ($record === null) {
        return false;
    }

    $this->setAttributes($record->getAttributes(), false);
    
    return true;
}

八、一个很多人忽略的坑

如果你这样写:

$model->updateAttributes([
    'status' => 1
]);

然后:

$model->refresh();

这一步其实 通常没必要

因为:

$model 本身已经是最新

refresh只是再查一次数据库。

九、refresh 不适用的情况

refresh 不能解决事务未提交的问题

例如:

事务 A:

$model->status = 1;
$model->save();

事务 B:

$model->refresh();

如果 A 没 commit

B 仍然读不到。

十、什么时候必须用 refresh

下面这几种情况推荐用:

数据库触发器

update_time

自增字段

sequence

其他服务修改

例如:

消息队列
websocket
异步任务

十一、实际开发建议

很多 Yii2 项目里常见写法:

$model->save(false);
$model->refresh();

作用就是:

确保当前对象状态 = 数据库状态

十二、总结一句话

refresh() 的本质就是:

重新 SELECT 当前记录
并覆盖当前 AR 对象属性

所以你说:

可以让模型刷新到最新吧?

答案是:

对,但前提是数据库里已经是最新数据。