yii2 timestampbehavior时间错误的核心原因是时间值类型、时区设置、数据库字段类型三者不匹配;需确保value返回值与字段类型一致(datetime用字符串、int用time())、php与mysql时区统一(如asia/shanghai)、避免数据库默认值与行为冲突,并排查beforesave等逻辑覆盖。

Yii2 的 TimestampBehavior 时间不对,核心原因通常不是行为本身出错,而是**时间值类型、时区设置、数据库字段类型三者不匹配**。只要理清这三点,修正起来很直接。
检查 value 返回值是否匹配数据库字段类型
数据库字段是 DATETIME(如 created_at DATETIME),value 就不能返回整型时间戳(time()),否则会存成 1970-01-01 08:00:01 这类错误时间。
- 字段为
DATETIME或TIMESTAMP:value 应返回字符串格式,例如function () { return date('Y-m-d H:i:s'); } - 字段为
INT或BIGINT:保持value => time()即可 - 更稳妥的做法是交由 MySQL 生成:
'value' => new \yii\db\Expression('NOW()'),避免 PHP 与数据库时区差异
确认 PHP 和 MySQL 时区是否一致
即使 value 返回了正确格式,若 PHP 用 date('Y-m-d H:i:s') 生成时间,而 MySQL 实际按 UTC 存储,就会差 8 小时(以东八区为例)。
- 在入口文件(如
web/index.php)开头加:date_default_timezone_set('Asia/Shanghai'); - 检查 MySQL 当前时区:
SELECT @@global.time_zone, @@session.time_zone; - 推荐统一设为系统时区或
+08:00,避免依赖CURRENT_TIMESTAMP的自动行为
排查模型或数据库默认值冲突
如果数据库字段设置了 DEFAULT CURRENT_TIMESTAMP,又同时启用 TimestampBehavior,两者可能打架——尤其在更新操作中,行为写入一次,数据库又覆盖一次。
- 关闭字段的数据库默认值,完全交由 Yii 行为控制
- 或关闭模型的默认值加载:
public $loadDefaultValues = false; - 也可在行为配置中显式排除该字段,避免重复赋值
验证时间字段是否被其他逻辑覆盖
常见干扰源包括:beforeSave() 手动赋值、表单提交带入空/非法时间、批量赋值(load())未过滤字段。
- 在
beforeSave()中检查是否误写了$this->created_at = ...,与行为冲突 - 确保表单提交的时间字段名与行为监听字段名完全一致(大小写、下划线)
- 使用
safe规则限制可批量赋值字段,防止外部传入脏数据覆盖行为结果











