应先查看PDOException的message字段获取真实错误:如“Connection refused”表示服务未启动或网络不通,“Access denied”为认证失败,“No such file or directory”则指向socket路径问题;再针对性排查host、port、env加载及MySQL 8.0认证插件等。

直接看 PDOException 的 message 字段,别猜。它说 “Connection refused” 就是服务没起来,“Access denied” 就是账号权限或密码错,“No such file or directory” 多半是 localhost 和 socket 路径对不上。
怎么看真实的 PDO 错误信息
ThinkPHP 本身不造错,它只是把 PDO 抛出来的异常原样往上扔。关键线索全在 PDOException 的 message 里:
- "SQLSTATE[HY000] [2002] Connection refused" → MySQL 没启动,或
hostname/hostport配得和实际监听地址/端口不一致 - "SQLSTATE[HY000] [1045] Access denied for user" → 用户名密码错,或该用户只允许从
'localhost'连,而 PHP 实际运行环境(比如 Docker 容器)IP 不是localhost - "SQLSTATE[HY000] [2002] No such file or directory" → 配了
localhost,但 MySQL 没开 Unix socket,或路径不对(常见于 Mac M1 + Homebrew)
别只盯着浏览器上“数据库连接失败”这句空话。去 runtime/log/ 找最新日志,复制完整 PDOException 行,重点盯 message 后面那段。
host 写 127.0.0.1 还是 localhost?
绝大多数情况下,hostname 必须写 127.0.0.1,不能写 localhost:
立即学习“PHP免费学习笔记(深入)”;
-
localhost在多数系统下强制走 Unix socket 连接,而 ThinkPHP 默认用 TCP;两者不匹配,就会报 “No such file or directory” -
127.0.0.1明确走 TCP,和hostport参数语义一致 - Docker 环境中,
127.0.0.1指容器自己,不是宿主机 —— 此时得换成容器名(如mysql)或host.docker.internal - 云服务器上,MySQL 用户的
host字段必须是%或具体公网 IP,不能是localhost,否则远程连不进
.env 文件配置没生效?先验这三点
.env 不是写了就能用,它有硬性前提:
-
.env文件必须放在项目根目录(和think命令同级),不是config/或app/下 -
APP_DEBUG必须为true,否则环境变量加载逻辑会被跳过 —— 这是最常被忽略的一点 - 键名必须全大写加下划线:
DB_HOST=127.0.0.1才有效,db_host或Db_Host都读不到
验证是否加载成功:控制器里临时加一行 dump(env('DB_HOST'));。输出 null 就说明上面至少有一条没满足。
MySQL 8.0+ 报 caching_sha2_password 错误
错误信息是:Authentication plugin 'caching_sha2_password' cannot be loaded。这不是 ThinkPHP 的问题,是 PHP 7.4 以下版本的 pdo_mysql 扩展不支持 MySQL 8.0 默认认证方式。
- 不要降级 MySQL,改用户认证方式即可:
ALTER USER 'your_user'@'%' IDENTIFIED WITH mysql_native_password BY 'your_pass'; - 执行后记得
FLUSH PRIVILEGES; - 如果用户是
'root'@'localhost',就把%换成localhost - 确认
php -m输出里有pdo_mysql;没有就检查php.ini是否启用了该扩展,并重启 Web 服务
复杂点在于:同一个 MySQL 实例可能混用多种认证方式,SELECT user, host, plugin FROM mysql.user; 看清目标用户的 plugin 列再动手,别全局改错人。



















