ThinkPHP 6 连不上数据库主因是 .env 优先覆盖 config/database.php 配置,且密码含特殊字符需 URL 编码、本地应使用 127.0.0.1 而非 localhost;connections 与 default 必须匹配,SSL 参数须通过 params 数组传 PDO 常量并用绝对路径。

ThinkPHP 6 默认走 config/database.php 配置,但如果你启用了 .env,它会优先覆盖——改配置没生效,八成是被 .env 拦住了。
为什么改了 database.php 却连不上数据库
ThinkPHP 6 启动时会先检查项目根目录是否存在 .env 文件。只要存在且包含 DB_HOST、DB_NAME 等键,框架就会直接用它,config/database.php 里对应项会被忽略。
- 常见现象:
config/database.php明明写了'hostname' => '127.0.0.1',但报错显示连的是localhost—— 很可能.env里有DB_HOST=localhost - 密码含特殊字符(如
@、/、:)必须 URL 编码,例如pa@ss/word要写成pa%40ss%2Fword,否则解析失败导致空密码 - 本地开发务必用
127.0.0.1,别写localhost;MySQL 在 Unix 系统下会尝试走 socket 连接,而 TP6 的 PDO 默认走 TCP,容易报Connection refused
database.php 中的 connections 和 default 怎么配才有效
connections 是连接池定义区,每个键名(如 'mysql'、'admin')代表一个独立连接配置;default 则指定哪个连接名作为全局默认入口。两者必须匹配,否则启动就报错。
-
default的值必须是connections数组中已存在的键名,比如'default' => 'admin',那connections里就必须有'admin' => [...] - 连接名不能和内置驱动名冲突,例如别起名叫
'mysql'(除非你真要覆盖默认 MySQL 驱动),推荐用业务语义名,如'user_db'、'log_db' - 如果只用一个库,最简写法是直接在
connections['mysql']里填参数,再设'default' => 'mysql';不需要额外嵌套或删减字段 -
prefix设为空字符串('')更安全,尤其后续可能跨库查询,避免表名被自动拼上前缀导致查不到
SSL 连接必须通过 params 数组传 PDO 常量,不是拼 DSN
ThinkPHP 6 不识别 DSN 字符串里写的 ?ssl_mode=REQUIRED,也不接受小写键名如 'mysql_attr_ssl_ca'。SSL 参数唯一合法位置是连接配置的 params 数组,且键必须是 PDO 常量。
立即学习“PHP免费学习笔记(深入)”;
- CA 证书路径必须是服务器本地绝对路径,
/etc/mysql/ssl/ca.pem可以,./cert/ca.pem或https://...会失败 - 自签名内网环境用
PDO::MYSQL_ATTR_SSL_MODE => PDO::MYSQL_ATTR_SSL_MODE_REQUIRED,别用VERIFY_IDENTITY(它校验域名,多数不满足) - 私钥文件不能设密码,PHP 进程读取时无法交互输入;且权限需为 600,否则 PDO 报
SSL operation failed - 若 MySQL 服务端未启用 SSL(
SHOW VARIABLES LIKE '%ssl%'中have_ssl为DISABLED),TP6 配得再对也没用
连接池(deploy => 1)比 PDO 持久化更可靠
直接在 params 里加 PDO::ATTR_PERSISTENT => true 基本无效——TP6 的 Connection 类在销毁时主动置空 $this->pdo,绕过了 PDO 持久化机制。
- 真正起作用的是把
deploy设为1,这会启用框架内置连接复用逻辑,即使没配主从也生效 - 配合
'pool_size' => 20可控最大空闲连接数,防止 MySQL 端max_connections耗尽 - 该机制只对「同 hostname + 同 database + 同账号密码」的请求复用;换库名或改密码会新建连接池,不是全局长连接
- MySQL 侧建议同步调大
max_connections(如设为 500),并确认wait_timeout不过短(默认 28800 秒通常够用)
最容易被忽略的是 .env 的优先级和 SSL 证书路径的绝对性——前者让很多人白调半天配置,后者让 SSL 报错卡在文件权限或格式上,而不是代码逻辑。



















