模型修改器仅在模型实例的save()中触发,where()->update()、Db::table()等直接SQL操作及new Model([])构造均不触发;需用get()/find()查出实例再save()或data($data, true)赋值。

save() 更新时修改器没跑?检查是否用了 where()->update()
模型修改器只在模型层的写入逻辑中触发,where()->update() 是数据库查询构造器直接执行 SQL,完全绕过模型事件、获取器和修改器。哪怕你继承了 think\Model,只要调用的是 update() 方法(包括静态调用 UserModel::update()),setXxxAttr 就不会执行。
常见错误写法:
$user = new UserModel();
$user->where('id', 1)->update(['password' => 'raw']); // ❌ 不触发 setPasswordAttr
UserModel::update(['id' => 1, 'password' => 'raw']); // ❌ 同样不触发
正确做法是先查出模型实例再改再保存:
- 用
UserModel::get(1)或UserModel::find(1)获取模型对象 - 赋值后调用
$user->save(),此时setPasswordAttr才会生效 - 或者用
save()的条件更新形式:$user->save(['password' => 'raw'], ['id' => 1])—— 这个会触发修改器
实例化传参或 data() 赋值没加 true 参数?修改器被跳过了
new UserModel(['password' => 'raw']) 这种构造方式,数据直接塞进属性,不走任何修改器;$model->data(['password' => 'raw']) 默认也不会触发修改器,除非第二个参数显式传 true。
立即学习“PHP免费学习笔记(深入)”;
原因在于:ThinkPHP 5.1 中 data() 方法默认只做原始赋值,只有 $model->data($data, true) 才会启用字段过滤 + 修改器处理。
所以这些写法都不触发修改器:
$user = new UserModel(['password' => 'raw']);-
$user->data(['password' => 'raw']);(缺第二个参数) -
$user->allowField(true)->data($_POST);(依然缺true)
要确保触发,必须写成:
$user = new UserModel(); $user->data(['password' => 'raw'], true); // ✅ 第二个参数为 true $user->save();
字段名和方法名大小写/下划线不匹配?修改器根本找不到
ThinkPHP 5.1 修改器命名严格遵循 set + 字段名首字母大写 + Attr 规则,且区分大小写和下划线。比如数据库字段是 user_name,方法名必须是 setUserNameAttr,不是 setUsernameAttr,也不是 setUser_nameAttr。
常见踩坑点:
- 字段
create_time→ 方法名必须是setCreateTimeAttr,写成setCreatetimeAttr或setCreate_timeAttr都无效 - 字段
is_deleted→ 方法名是setIsDeletedAttr,不是setIs_deleteAttr - 方法定义在父类里,但子类模型没继承或重写了同名方法,也会导致不触发
建议打开调试模式,在修改器方法第一行加 trace('setPasswordAttr triggered'); 确认是否真被调用。
用了 Db::table() 或原生 SQL?模型修改器天然不生效
只要脱离了模型实例,一切修改器都失效。Db::table('user')->update(...)、Db::execute()、$model->query() 这些操作都在数据库层完成,模型层的逻辑(包括修改器、自动完成、事件)全部被跳过。
如果你需要加密、格式化等逻辑,又不得不走原生 SQL,只能手动处理:
- 在调用
Db::table()->update()前,自己调用setPasswordAttr('raw')处理值 - 或者封装一个工具函数统一处理敏感字段,避免散落在各处
- 更稳妥的方式是:把这类逻辑收口到模型方法里,比如
public function updateWithEncrypt($data),内部走$this->save($data)
修改器本质是模型生命周期的一部分,它只活在模型对象的写入流程里——离开这个上下文,它就不存在。



















