Connection refused本质是操作系统或数据库服务拒绝连接,非ThinkPHP本身问题;需通过PDOException::getMessage()定位真实原因,如[2002]表示服务未启动或地址端口不匹配,[1045]为权限问题,[2002]加“No such file”则指向Unix socket路径错误。

Connection refused 不是 ThinkPHP 的错,是 PHP 尝试建立 socket 连接时被操作系统或 MySQL/Redis 服务直接拒绝——说明服务没在监听,或者监听的地址端口跟配置对不上。
怎么看 PDOException 的真实错误信息
ThinkPHP 只是透传 PDO 抛出的异常,关键线索全在 PDOException::getMessage() 里:
-
"SQLSTATE[HY000] [2002] Connection refused"→ MySQL 进程没启动,或hostname/hostport配得完全不对 -
"SQLSTATE[HY000] [1045] Access denied for user"→ 用户权限不匹配(比如配置连的是127.0.0.1,但数据库里只建了'user'@'localhost') -
"SQLSTATE[HY000] [2002] No such file or directory"→ 配了localhost却没启用 Unix socket,或路径压根不存在(Mac M1 Homebrew 默认 socket 路径是/opt/homebrew/var/mysql/mysql.sock)
别只看日志里“数据库连接失败”这句空话。去 runtime/log/ 找最新日志,复制整条带 PDOException 的 message 再判断。
为什么 host 和 port 看似写对了还是 Connection refused
常见错位不在拼写,而在网络语义和类型隐式转换:
立即学习“PHP免费学习笔记(深入)”;
-
hostname别写localhost:它在多数系统下强制走 Unix socket,而你配的hostport是给 TCP 用的,两者不兼容;统一改用127.0.0.1测试 -
hostport必须是整数:写成'3306'(字符串)会导致 ThinkPHP 8 传给 PDO 时 fallback 到默认端口(如 0),实际连到错的地方 - Docker 环境中,
hostname不能写127.0.0.1或localhost,得换成容器名(如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 8.0 默认认证方式。
- 登录 MySQL 命令行,执行:
ALTER USER 'your_user'@'%' IDENTIFIED WITH mysql_native_password BY 'your_password'; - 注意
@'%'要跟你 PHP 实际连接来源一致(比如是 Docker 容器,就用@'172.x.x.x'或@'%') - 执行
FLUSH PRIVILEGES;生效 - 确认
phpinfo()里已启用pdo_mysql扩展,且 PHP 版本 ≥ 7.2
复杂点在于:同一个用户名在不同 host 下可能对应不同认证插件,SELECT user, host, plugin FROM mysql.user 必须查清楚实际匹配的是哪一条记录。



















