laravel 修改器仅在模型属性赋值时触发,需手动写入 $this->attributes,命名须为 set{attributename}attribute,不处理日期/json(应使用 $casts),且读写需配合访问器才能统一格式。

修改器只在模型属性被赋值时触发,不是数据库更新钩子,别指望它能替代 DB::table()->update()。
set{AttributeName}Attribute 方法必须手动写入 $this->attributes
修改器不会自动把处理后的值塞进数据库字段,你得自己动手赋值。Laravel 只负责调用你的方法,不接管后续逻辑。
- 方法名必须严格遵循
set{AttributeName}Attribute格式,比如数据库字段是user_name,就得写成setUserNameAttribute - 参数是传入的原始值(
$value),你处理完后必须显式写入:$this->attributes['user_name'] = $processedValue - 不能
return任何东西,Laravel 完全忽略返回值 - 如果字段名含下划线,驼峰转换要准确:数据库字段
profile_data→ 方法名setProfileDataAttribute
修改器对批量操作生效,但只认模型已知字段名
使用 create()、fill()、update() 时,修改器会触发 —— 前提是数组键名能匹配到模型里定义的修改器所对应的属性名。
-
User::create(['user_name' => 'ABC'])→ 触发setUserNameAttribute -
User::create(['name' => 'ABC'])→ 不触发,除非你有name字段且定义了setNameAttribute -
$user->fill(['user_name' => 'XYZ'])→ 同样触发,但$user->fill(['username' => 'XYZ'])不会(字段名不匹配)
别在修改器里处理日期或 JSON,优先用 $casts
手动在 setCreatedAtAttribute 里转时间戳,容易绕过 Laravel 的时区处理和 Carbon 实例化逻辑,导致读写行为不一致。
- 日期字段统一走
$casts = ['created_at' => 'datetime']或自定义格式如'published_at' => 'custom_datetime:YmdHis' - JSON 字段直接用
'settings' => 'array',不用手写json_encode/json_decode - 真要加密敏感字段(如手机号),也建议封装进
Attribute类或独立服务,避免修改器里混入业务强逻辑
最常被忽略的一点:修改器和访问器完全解耦。只定义修改器,读出来的还是数据库原值;想读写都统一格式,访问器也得同步配一个。否则你会看到存进去是小写邮箱,取出来却是大写——因为没定义 getEmailAttribute。这种错很难 debug,尤其当字段值看起来“差不多”的时候。











