ThinkPHP6模型修改器不生效的三大主因是:未走模型层(如Db直连、data()未加true参数)、命名不匹配驼峰规则(如user_name须对应setUserNameAttr)、字段被$hidden/$readonly/$field等配置拦截。

ThinkPHP6模型修改器不生效,通常不是代码写错了,而是被框架的执行条件悄悄拦下了。核心问题就三个:没走模型层、命名不对、字段被屏蔽。下面按高频场景逐个拆解。
检查是否绕过了模型写入流程
修改器只在模型的 save()、create() 等方法中触发,其他方式一律跳过:
-
Db类直连操作完全无效:如
Db::name('user')->update(['password' => '123']),不会调用setPasswordAttr -
data() 方法需显式传参:写成
$user->data(['password' => '123'])不触发;必须加第二个参数true:$user->data(['password' => '123'], true) -
构造时直接赋值会失效:在
__construct()或初始化里写$this->password = '123',会导致值提前进$this->data,后续 save() 时跳过修改器
确认方法命名与字段严格匹配
TP6 对驼峰转换非常敏感,错一个字母或下划线位置就静默失效:
- 数据库字段是
user_name,方法名必须是setUserNameAttr(U和N大写),不能是setUsernameAttr或set_user_nameAttr - 字段含数字或特殊符号,如
api_v2_token,对应方法是getApiV2TokenAttr,下划线后紧跟的字母必须大写 - 方法必须只有一个参数
$value,不要写成($value, $data)—— TP6.1+ 已移除第二个参数支持
排查字段是否被模型配置拦截
即使方法写对了,字段也可能被“看不见”的配置挡在外面:
立即学习“PHP免费学习笔记(深入)”;
-
$hidden 数组会彻底禁用访问器和修改器:如果写了
protected $hidden = ['password'],setPasswordAttr根本不会运行,删掉或改用$visible显式声明 -
$readonly 字段禁止写入:若
protected $readonly = ['password'],哪怕修改器存在,赋值也会被丢弃 -
$field 白名单漏掉字段:如
protected $field = ['id', 'username']却没包含'password',save() 时该字段直接被过滤,修改器无从触发
验证继承与环境基础
底层前提不满足,上层逻辑全白搭:
- 模型类必须 继承
think\Model,不是think\db\Model或其他基类 - 确保不是在 CLI 或单元测试中漏掉语言/环境加载——但修改器本身不依赖 Lang,这点可暂不查
- OPcache 开启可能导致代码修改延迟生效(尤其 PHP 7.3+),临时关闭
opcache.enable=0并重启服务可快速验证是否为缓存干扰



















