thinkphp6模型修改器加密失败主因是未触发或写法错误:须继承think\model、严格命名setpasswordattr、仅save()/create()触发;密码加密必用password_hash()配判空与长度校验,禁用md5/sha1;敏感字段加密需可逆算法、配置密钥、固定iv、双写索引。

ThinkPHP6模型修改器加密失败,核心问题往往不在加密逻辑本身,而在于“没触发”或“触发了但写法不对”。只要确认是走save()或create()写入,且模型继承正确,90%的问题都能快速定位。
检查修改器是否真正被调用
修改器不是全局钩子,它只在特定条件下激活:
- 模型类必须继承
think\Model(不是think\db\Model或其他基类) - 方法名必须严格为
setPasswordAttr(字段叫pwd就得写setPwdAttr),大小写、下划线、前缀一个都不能错 - 必须通过模型实例的
save()、create()或data()->save()写入;Db::name('user')->update([...])或$model->where()->update(...)完全绕过修改器 - TP6.1+ 中,
setXxxAttr参数只接收一个值($value),别写成($value, $data)
密码加密写法必须合规
用 password_hash() 是唯一推荐方式,但细节决定成败:
- 判空处理不可少:
if (empty($value)) return null;,否则password_hash(null)返回false,导致入库失败 - 长度校验建议加上:
if (strlen($value) > 72) throw new Exception('Password too long');,避免算法截断风险 - 别用
md5、sha1或拼接盐值——它们不安全,也不符合现代密码存储规范 - 推荐
PASSWORD_DEFAULT(当前等价 bcrypt),环境支持可选PASSWORD_ARGON2ID;cost => 12可显式指定
敏感字段加密(如手机号、身份证)常见翻车点
这类字段要用可逆加密,和密码哈希完全不同:
- 禁用
password_hash()和md5()——解不开就等于数据丢失 - 密钥必须从配置读取:
config('app.aes_key'),不能硬编码;AES-128 要 16 字节,AES-256 要 32 字节 - IV 必须固定衍生(如
substr(hash('sha256', $key), 0, 16)),不能每次随机,也不能全局复用 - 数据库字段类型设为
VARCHAR(255)或TEXT,排序规则用utf8mb4_bin,避免 Base64 密文被截断 - 查询时不能直接
where('phone', '138...')——得先加密条件,或采用「明文索引 + 密文存储」双写方案
调试与验证技巧
别靠猜,用最直接的方式确认问题所在:
- 在修改器开头加
trace('setPasswordAttr triggered: ' . $value);,查runtime/log/看日志是否出现 - 用
dump($this->getData())在save()前打印原始数据,确认字段名和值是否传入正确 - 测试时用最小化代码:
$user = new User(); $user->password = '123'; $user->save();,排除控制器或验证层干扰 - 登录验证必须用
password_verify($input, $hash),不能用===或hash_equals()比对哈希串
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











