绝大多数场景下优先用 Db::raw('NOW()'),因其由数据库生成时间戳,可规避时区不一致、PHP与MySQL时间不同步、并发写入顺序错乱及索引失效等问题;仅在需PHP层控制时区、精度或业务逻辑判断时才用time()。

ThinkPHP 更新时间戳字段该用 Db::raw 还是 time()
直接说结论:**绝大多数场景下,优先用 Db::raw('NOW()')(或 Db::raw('CURRENT_TIMESTAMP')),而不是 PHP 的 time()。除非你明确需要 PHP 层控制时间精度、时区或做逻辑判断。**
为什么 Db::raw('NOW()') 更安全可靠
数据库服务端生成时间戳,能规避时区不一致、PHP 与 MySQL 时间不同步、高并发下毫秒级写入顺序错乱等问题。
-
time()返回的是 PHP 进程所在服务器的 Unix 时间戳,若 PHP 和 MySQL 不在一台机器、或系统时钟未同步,会导致时间偏差 - MySQL 的
NOW()是事务开始时刻的时间(可重复读隔离级别下),而time()是 PHP 执行那行代码的瞬间,中间可能有网络延迟、其他逻辑耗时 - 使用
Db::raw('NOW()')可被数据库自动识别为时间类型,避免字符串隐式转换导致索引失效(比如字段是DATETIME,但传了'1717023600'字符串)
什么时候必须用 time() 或 PHP 时间函数
只有当你需要和业务逻辑强绑定时间值,或绕过数据库默认行为时才考虑。
- 要统一用北京时间(而 MySQL 服务器时区是 UTC):先
date('Y-m-d H:i:s', time() + 8 * 3600)再传入 - 更新字段时需“只在满足条件时覆盖时间”,例如
['update_time' => $condition ? time() : Db::raw('update_time')] - 批量更新中,希望每条记录的时间戳略有差异(如模拟用户操作间隔),这时
time()加微秒偏移更可控
常见错误和兼容性注意点
踩坑最多的是混用类型和忽略字段类型定义。
立即学习“PHP免费学习笔记(深入)”;
- 对
TIMESTAMP字段用Db::raw('UNIX_TIMESTAMP()')→ 错!会写入整数而非时间,导致查询异常或自动转成 1970 年 - 用
date('Y-m-d H:i:s')但没格式化秒级精度 → MySQL 可能截断,且无法利用DATETIME索引范围查询 - ThinkPHP 6.0+ 中,
Db::raw()在update()数组里不会自动加引号,但若字段是字符串类型(如VARCHAR存时间),必须手动包单引号:Db::raw("'".date('Y-m-d H:i:s')."'") - SQLite 不支持
NOW(),得用datetime('now');PostgreSQL 用CURRENT_TIMESTAMP更标准
最易被忽略的一点:如果你在模型中启用了自动时间戳(protected $autoWriteTimestamp = true),再手动用 Db::raw 或 time() 赋值同名字段,会触发两次赋值,后者覆盖前者 —— 这种隐式冲突很难 debug。



















