ThinkPHP 6.0 已彻底移除 $_auto 属性和旧版自动完成机制,必须改用模型事件(before_insert/before_update)或访问器(Mutator)实现字段自动处理,时间戳推荐直接使用内置 createTime/updateTime 配置。

ThinkPHP 6.0 已完全移除 $_auto 属性和旧版自动完成机制,直接沿用 TP5.1 的 $insert / $update / $auto 三数组方式会报错或静默失效。
TP6.0 中 $auto 属性已废弃,必须改用事件或访问器
TP6.0 的模型自动完成不再依赖属性配置,而是通过模型生命周期事件(如 before_insert、before_update)或访问器(Accessor / Mutator)实现。官方明确表示:
-
$_auto在 TP6.0 中被彻底删除,任何残留定义都会被忽略 -
$auto属性虽仍可声明,但框架不再读取它,不会触发填充逻辑 - 使用
create()方法也已废弃,数据创建统一走save()或data()->save()
常见错误现象:
- 表单提交后
create_time字段始终为空,即使写了array('create_time', 'time', 1, 'function') -
password字段未被md5处理,直接存明文 - 控制器中调用
$model->create($data)报Method create does not exist
正确做法:
- 在模型类中监听
before_insert事件,手动设置字段值 - 对密码等敏感字段,优先使用 Mutator(
setPasswordAttr)做写入前处理 - 时间戳推荐直接用模型内置的
createTime/updateTime配置,而非手动填充
用 before_insert 和 before_update 替代自动完成
这是最接近旧版 $_auto 行为的迁移方案,适合需要条件判断或跨字段逻辑的场景。
示例:自动设置部门编号与创建时间
protected static function init()
{
self::event('before_insert', function ($model) {
$model->dept_id = $model->dept_id ?: self::getDeptIdByRole($model->role);
$model->create_time = time();
$model->status = 1;
});
<pre class="brush:php;toolbar:false;">self::event('before_update', function ($model) {
$model->update_time = time();
// 注意:此处不能改 $model->id 或主键,否则 save() 可能失效
});}
protected static function getDeptIdByRole($role) { return ['admin' => 1, 'editor' => 2, 'guest' => 3][$role] ?? 3; }
关键注意点:
- 事件回调函数接收的是
$model实例,不是原始数据数组 - 不要试图在事件里修改
$model->data数组,应直接赋值属性 -
before_update触发时,模型已加载原记录,可对比旧值做逻辑(如仅当 status 变更时记录日志) - 若需兼容新增/更新统一处理,可监听
before_write,但它不区分操作类型
Mutator(setXxxAttr)更适合字段级转换
对密码哈希、字符串标准化、JSON 编码等「单字段确定性转换」,Mutator 更安全、更直观,且天然支持批量赋值。
示例:密码自动加密 + 状态字段标准化
protected function setPasswordAttr($value)
{
return $value ? md5($value) : '';
}
<p>protected function setStatusAttr($value)
{
return in_array($value, [0, 1, 2]) ? (int)$value : 1;
}</p><p>protected function setContentAttr($value)
{
return trim(htmlspecialchars($value));
}
</p>
使用效果:
-
$user->password = '123456'; $user->save();→ 自动存入md5('123456') -
$user->data(['status' => 'on'])->save();→status被转为1 - Mutator 不受事件顺序影响,比 before_* 更早执行,且对
create()(如果自定义了)也生效
时间戳别硬写,用模型内置配置更稳
TP6.0 原生支持时间戳字段自动管理,无需手写事件或 Mutator。
在模型中声明:
protected $createTime = 'create_time'; protected $updateTime = 'update_time'; protected $autoWriteTimestamp = true; // 或设为 'datetime' / 'timestamp'
效果:
- 新增时自动写入
create_time和update_time - 更新时只改
update_time - 若数据库字段是
DATETIME类型,设$autoWriteTimestamp = 'datetime',避免时间戳转成 1970 年
容易踩的坑:
- 忘记开启
$autoWriteTimestamp,只设字段名无效 - 字段名拼错(如写成
created_at却配了$createTime = 'create_time') - 手动赋值了
create_time,会覆盖自动写入值 —— 如需保留手动控制,设$autoWriteTimestamp = false再用事件
真正复杂的地方在于:事件和 Mutator 的执行时机有重叠,混用时可能重复处理(比如既在 before_insert 里设了 password,又写了 setPasswordAttr)。实际项目中建议二选一,优先用 Mutator 做字段级转换,用事件做业务逻辑(如关联写日志、触发通知)。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











