pdoexception的message字段才是真实报错源头,如“[2002] connection refused”表示服务未启动,“[1045] access denied”说明认证失败,“[2002] no such file”指向socket路径问题,须据此精准排查。

PDOException 的 message 字段才是真实报错源头,别在 database.php 里盲目改配置——先看它说什么。
怎么看 PDOException 的真实错误信息
ThinkPHP 不自己抛连接错误,它只是把 PDO 层的异常原样往上扔。关键就藏在 message 里:
-
"SQLSTATE[HY000] [2002] Connection refused"→ MySQL 服务根本没启动,或 host/port 不通 -
"SQLSTATE[HY000] [1045] Access denied for user"→ 用户名、密码、host 三者中至少一个不匹配(比如数据库里是'root'@'localhost',但 PHP 在 Docker 容器里跑) -
"SQLSTATE[HY000] [2002] No such file or directory"→ 配置写了localhost,但 MySQL 没开 socket,或路径不对(Mac M1 Homebrew 安装常见)
别只盯着日志里“数据库连接失败”这句废话。直接翻 runtime/log/ 下最新日志,找到带 PDOException 的那一行,复制完整 message 再判断。
host 和 port 看似写对了,为什么还是连不上
错位点常不在语法,而在网络语义:
- host 别写
localhost:它在多数系统下强制走 Unix socket;而你配的port是给 TCP 用的,两者不匹配。统一用127.0.0.1测试 - port 必须是整数:
'3306'(字符串)会导致 ThinkPHP 5.1+ 传给 PDO 时类型不符,PDO 会静默 fallback 到默认端口 - Docker 环境中,host 不能写
127.0.0.1或localhost,得换成容器名(如mysql)或宿主机网关(如host.docker.internal) - 云服务器上,MySQL 用户的
host字段必须是'%'或具体公网 IP,不能是'localhost'——否则远程请求直接被拒
.env 文件覆盖配置没生效,怎么快速验证
.env 不是写了就能用,它有三个硬性前提:
- 文件必须放在项目根目录(和
think命令同级),不是config/或app/下 -
APP_DEBUG必须为true,否则环境变量加载逻辑会被跳过(这是最常被忽略的一点) - 键名必须全大写加下划线:
DB_HOST=127.0.0.1才有效,db_host或Db_Host都读不到
验证是否加载成功,控制器里临时加一行:dump(env('DB_HOST'));。输出 null 就说明上面三点至少有一条没满足。
ThinkPHP 6.1+ 报 Driver [mysql] not supported 怎么办
升级到 ThinkPHP 6.1 或更高版本后,mysql 驱动名已被废弃,直接写 'type' => 'mysql' 会触发该错误。核心原因是底层驱动注册机制变了。
- 把数据库配置中的
'type' => 'mysql'改成'type' => 'pdo_mysql' - 确认已安装
pdo_mysql扩展(运行php -m | grep pdo_mysql验证) - 若用的是 MySQL 8+,需额外检查
charset是否设为utf8mb4,否则可能连上但插入 emoji 失败
还有个隐藏坑:旧版代码或第三方扩展里如果还硬编码了 think\db\connector\Mysql,也会报错。全局搜 use think\db\connector\Mysql,替换成 use think\db\connector\PdoMysql。
127.0.0.1 指向容器自身而非宿主机。这些细节不验证,光改配置只会越调越乱。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











