Eloquent 中不存在“Attribute Self-Transitions”这一官方概念,实为对访问器/修改器(get/set)或 $casts 的误称;真正支持属性读写时自动转换的只有这两种标准机制。

什么是 Eloquent Attribute Self-Transitions?
PHP 中并没有官方叫法为 “Eloquent Attribute Self-Transitions” 的功能,Laravel 也从未在文档中定义或支持这个术语。它大概率是某些中文技术文章对 get*/set* 访问器(Accessors/Mutators)或 casts 配置的误称,混入了状态机(state machine)概念后产生的混淆表达。
真正能实现“属性读写时自动转换”的,只有两种标准机制:访问器/修改器(用于运行时逻辑处理),和模型 $casts(用于类型强制转换,如 'active' => 'boolean')。
用 Accessor/Mutator 实现读写时的自定义转换
当你需要在取值或赋值时执行逻辑(比如把数据库存的 'draft' 映射为布尔 true,或把时间戳转为 Carbon 实例),get* 和 set* 方法是最直接的方式。
-
get*方法名必须以get开头、属性名首字母大写、结尾加Attribute,例如数据库字段为status,则方法名为getStatusAttribute -
set*方法同理,如setStatusAttribute,参数是传入的原始值 - 这些方法不会影响数据库查询条件,仅作用于模型实例的属性访问
- 若同时定义了
$casts和 accessor,$casts会先执行,accessor 再基于转换后的值运行
示例:
立即学习“PHP免费学习笔记(深入)”;
class Post extends Model
{
protected $casts = [
'published_at' => 'datetime',
];
public function getIsPublishedAttribute()
{
return $this->published_at && $this->published_at->isPast();
}
public function setStatusAttribute($value)
{
$this->attributes['status'] = match ($value) {
true, 'publish', 'published' => 'published',
false, 'draft' => 'draft',
default => $value,
};
}
}
什么时候该用 $casts 而不是 Accessor?
$casts 更轻量、更底层,适合类型层面的无歧义转换,且会被 Laravel 自动应用于查询构造器(比如 where('active', true) 会自动转成 where('active', 1))。
- 布尔型:用
'active' => 'boolean',底层调用 PHPfilter_var($value, FILTER_VALIDATE_BOOLEAN) - 日期类:用
'created_at' => 'datetime:Y-m-d',支持格式化输出(仅限访问时) - 数组/JSON:用
'options' => 'array',要求字段是 TEXT 或 JSON 类型 - 注意:
$casts不支持复杂业务逻辑,比如依赖其他字段、查库、发请求等
错误用法示例(会导致查询失效):
// ❌ 错误:$casts 里不能写函数调用
protected $casts = [
'is_published' => function ($value) {
return $this->published_at && $this->published_at->isPast();
},
];
“状态刷新”其实是模型重载问题,不是属性转换
所谓“Laravel 状态刷新”,常见场景是:模型实例已存在,但数据库记录被外部修改(如另一个请求、队列任务、SQL 直接更新),此时原模型对象的属性仍是旧值。这不是属性转换问题,而是数据同步问题。
- 调用
$model->refresh()可从数据库重新加载所有属性(含访问器结果) - 调用
$model->reload()(Laravel 10.28+)效果相同,语义更清晰 - 如果只刷新某几个字段,用
$model->refresh(['status', 'updated_at']) - 注意:refresh 不会触发事件,也不会调用
boot或初始化逻辑
典型踩坑点:在监听模型事件(如 updated)里调用 $model->refresh(),可能造成无限循环或意外覆盖。
真正复杂的点在于:访问器逻辑是否依赖外部状态(比如缓存、配置、关联模型),这类“伪纯转换”容易在序列化、队列任务或 API 响应中表现不一致。别把它当成魔法,要明确每一步的输入来源和生命周期边界。



















