php 8.2 中 pdo 连接 mysql 时区应通过 pdo::mysql_attr_init_command 设置 '+08:00',确保每次新连接自动生效,避免 orm 或长连接场景遗漏;dsn 中 timezone 参数为备选,兼容性不如 init_command。

PHP 8.2 中,通过 database(如 PDO)获取 MySQL 连接时设置时区,核心是**在连接建立的第一时间就执行 SET time_zone 命令**,确保后续所有时间函数(如 NOW()、CURRENT_TIMESTAMP)和 TIMESTAMP 字段行为与 PHP 一致(例如都按东八区解释)。
推荐方式:PDO DSN 或初始化命令中指定
这是最可靠、无需手动干预每条查询的方法,适用于长连接、连接池或 ORM 场景:
- 使用
PDO::MYSQL_ATTR_INIT_COMMAND参数,在每次新连接创建后自动执行时区设置 - 必须用偏移量(如
'+08:00'),避免依赖系统 tzdata('Asia/Shanghai'可能失败) - 该命令在连接握手完成后立即执行,早于任何业务 SQL,且不受连接复用影响
示例代码:
$pdo = new PDO(
'mysql:host=localhost;dbname=test;charset=utf8mb4',
$user, $pass,
[
PDO::MYSQL_ATTR_INIT_COMMAND => "SET time_zone = '+08:00'",
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]
);
备选方式:DSN 中附加 timezone 参数(MySQL 5.7+ / 8.0)
部分新版 MySQL 驱动支持在 DSN 中直接声明时区,更简洁:
- 写法:
mysql:host=localhost;dbname=test;charset=utf8mb4;timezone='+08:00' - 注意:不是所有 PDO 版本/驱动都识别该参数,建议优先用
INIT_COMMAND方式以保证兼容性 - 若使用 Laravel,可在
config/database.php的mysql.options数组中加入对应项
不推荐的方式:手动执行 SET time_zone 后再查数据
这类做法容易遗漏,尤其在使用 ORM、Query Builder 或连接复用时:
- 比如在
mysqli_query($conn, "SET time_zone = '+08:00'")后才执行业务查询 —— 若中间有其他组件提前发了 SQL(如健康检查、预处理语句),时区可能未生效 - 对长连接(如 CLI 守护进程、Swoole),会话时区可能随连接存活而“漂移”,需定期重置(不可靠)
-
SET GLOBAL time_zone需 SUPER 权限,且重启失效,不适用于共享主机或云数据库
验证是否生效
连接建立后,可快速验证:
- 执行
SELECT @@session.time_zone,应返回+08:00 - 对比
SELECT NOW(), UTC_TIME(),差值应稳定为 8 小时(如 NOW=16:30,UTC=08:30) - 同时检查 PHP 层:
date_default_timezone_get()应为Asia/Shanghai或Etc/GMT-8(注意 GMT-8 表示东八区)
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











