应统一设置php时区为asia/shanghai,并在timestampbehavior中显式指定datetimezone,同时确保数据库时区一致。具体操作:在入口文件调用date_default_timezone_set('asia/shanghai');模型behaviors()中value设为new datetime('now', new datetimezone('asia/shanghai'));数据库推荐用datetime类型并保持时区同步。

Yii框架中使用 TimestampBehavior 时,若服务器时区与应用预期时区不一致(如服务器设为UTC而业务要求东八区),会导致 created_at、updated_at 等字段写入错误的时间戳——常见表现为比本地时间晚8小时。问题根源在于 PHP 默认使用系统时区,而 TimestampBehavior 调用 time() 或 new \DateTime() 时未显式指定时区。
统一设置 PHP 应用时区
在应用入口文件(如 web/index.php 或 console/yii)顶部添加:
date_default_timezone_set('Asia/Shanghai');
该设置影响所有基于系统时间的函数(time()、date()、strtotime() 等),是 TimestampBehavior 正常工作的基础。注意:不能依赖 php.ini 中的 date.timezone,因部分环境(如 Docker 容器)可能未正确加载或被覆盖。
为 TimestampBehavior 显式指定时区
在模型的 behaviors() 方法中,避免直接使用 'value' => time() 这类无时区上下文的写法。改用带时区的 \DateTime 实例:
'createdAt' => [
'class' => TimestampBehavior::class,
'createdAtAttribute' => 'created_at',
'value' => new \DateTime('now', new \DateTimeZone('Asia/Shanghai'))
],
同理处理 updatedAt。这样确保行为生成的时间值始终基于目标时区,不受服务器本地时区干扰。
数据库字段类型与存储策略对齐
确认数据库中时间字段类型合理:
- 若使用
DATETIME类型(推荐),应确保数据库服务器时区也设为Asia/Shanghai,或至少明确其与 PHP 层时区一致; - 避免混用
TIMESTAMP类型(自动转为 UTC 存储),除非你主动在读写层做时区转换; - 在迁移中显式指定默认值(如
$this->dateTime()->defaultValue(new \yii\db\Expression('NOW()')))时,需确认 MySQL 的time_zone设置是否匹配。
验证与调试建议
快速验证是否生效:
- 在控制器中临时输出:
var_dump(date('Y-m-d H:i:s'), (new \DateTime())->format('Y-m-d H:i:s'));,两结果应一致且符合本地时间; - 新建记录后查数据库,比对
created_at值与当前北京时间; - 启用 Yii 日志,查看 SQL 插入语句中的时间字面量是否为你期望的值。
不复杂但容易忽略。











