如何设置ThinkPHP模型中的自定义时间戳字段?

2026-05-06 18:501阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计727个文字,预计阅读时间需要3分钟。

如何设置ThinkPHP模型中的自定义时间戳字段?

ThinkPHP默认仅识别`create_time`和`update_time`作为时间戳字段,若数据库表使用的是`created_at`和`updated_at`或其它名称,必须显式配置,否则自动写入将失效。

在模型类中设置两个关键属性即可生效:

  • protected $createTime = 'created_at'; —— 指定创建时间字段名
  • protected $updateTime = 'updated_at'; —— 指定更新时间字段名(设为 false 可关闭自动更新)
  • 两者都需配合 protected $autoWriteTimestamp = true;(TP6 默认开启,但建议显式声明)

为什么设置了字段名,插入时还是没写入时间?

常见原因是字段未被纳入数据写入白名单。ThinkPHP默认对字段做安全过滤,如果 created_at 不在模型的 $schema 或数据库实际字段列表中,会被静默丢弃。

检查并确保以下任一条件满足:

立即学习“PHP免费学习笔记(深入)”;

  • 模型已正确关联数据表(protected $table = 'user';),且该表确实包含 created_at 字段
  • 使用了 protected $schema = ['id', 'name', 'created_at', 'updated_at']; 显式声明字段(TP6.1+ 推荐)
  • 或关闭字段验证:在模型中加 protected $filterField = false;(不推荐,仅用于调试)

手动触发时间戳写入的几种场景

有些操作(如 saveAll()、批量 insert()、原生 SQL)不会走模型的时间戳逻辑,需要手动补全:

  • 批量插入前,用 array_map() 补时间:['created_at' => date('Y-m-d H:i:s')]
  • 调用 save() 时传入 ['force' => true] 参数可强制写入时间戳字段(即使字段已存在)
  • data() 链式方法预设值:(new User())->data(['name' => 'a'])->save(); 仍会触发时间戳,但 insert() 不会

TP5 和 TP6 时间戳行为差异要点

TP5 默认使用 datetime 类型字段 + 字符串格式写入;TP6 默认转为 int 时间戳(秒级),容易导致字段类型不匹配报错。

统一行为建议:

  • 若字段是 DATETIME 类型,设置 protected $dateFormat = 'Y-m-d H:i:s';
  • 若字段是 INT 类型,保持默认,但注意 MySQL 的 timestamp 字段范围限制(1970–2038)
  • TP6 中 $autoWriteTimestamp 支持字符串值,如 'datetime''timestamp',比布尔值更灵活

最常被忽略的是:改了字段名却忘了同步改数据库字段类型和格式配置,结果插入 NULL 或 0 值——务必先查表结构,再配模型。

标签:PHPThinkPHP

本文共计727个文字,预计阅读时间需要3分钟。

如何设置ThinkPHP模型中的自定义时间戳字段?

ThinkPHP默认仅识别`create_time`和`update_time`作为时间戳字段,若数据库表使用的是`created_at`和`updated_at`或其它名称,必须显式配置,否则自动写入将失效。

在模型类中设置两个关键属性即可生效:

  • protected $createTime = 'created_at'; —— 指定创建时间字段名
  • protected $updateTime = 'updated_at'; —— 指定更新时间字段名(设为 false 可关闭自动更新)
  • 两者都需配合 protected $autoWriteTimestamp = true;(TP6 默认开启,但建议显式声明)

为什么设置了字段名,插入时还是没写入时间?

常见原因是字段未被纳入数据写入白名单。ThinkPHP默认对字段做安全过滤,如果 created_at 不在模型的 $schema 或数据库实际字段列表中,会被静默丢弃。

检查并确保以下任一条件满足:

立即学习“PHP免费学习笔记(深入)”;

  • 模型已正确关联数据表(protected $table = 'user';),且该表确实包含 created_at 字段
  • 使用了 protected $schema = ['id', 'name', 'created_at', 'updated_at']; 显式声明字段(TP6.1+ 推荐)
  • 或关闭字段验证:在模型中加 protected $filterField = false;(不推荐,仅用于调试)

手动触发时间戳写入的几种场景

有些操作(如 saveAll()、批量 insert()、原生 SQL)不会走模型的时间戳逻辑,需要手动补全:

  • 批量插入前,用 array_map() 补时间:['created_at' => date('Y-m-d H:i:s')]
  • 调用 save() 时传入 ['force' => true] 参数可强制写入时间戳字段(即使字段已存在)
  • data() 链式方法预设值:(new User())->data(['name' => 'a'])->save(); 仍会触发时间戳,但 insert() 不会

TP5 和 TP6 时间戳行为差异要点

TP5 默认使用 datetime 类型字段 + 字符串格式写入;TP6 默认转为 int 时间戳(秒级),容易导致字段类型不匹配报错。

统一行为建议:

  • 若字段是 DATETIME 类型,设置 protected $dateFormat = 'Y-m-d H:i:s';
  • 若字段是 INT 类型,保持默认,但注意 MySQL 的 timestamp 字段范围限制(1970–2038)
  • TP6 中 $autoWriteTimestamp 支持字符串值,如 'datetime''timestamp',比布尔值更灵活

最常被忽略的是:改了字段名却忘了同步改数据库字段类型和格式配置,结果插入 NULL 或 0 值——务必先查表结构,再配模型。

标签:PHPThinkPHP