ThinkPHP 8 数据库配置必须用.env,database.php仅作结构定义和兜底;.env全量覆盖connections配置,硬编码值会被整块丢弃,必须全部改用env()函数读取。

database.php里为什么不能留死值
ThinkPHP 8 启用 .env 后,config/database.php 中的 connections.mysql 配置块会被完全替换,不是“合并字段”,而是整块丢弃。你写 'hostname' => 'localhost',只要 .env 里有任意一个 DB_* 变量(哪怕只有 DB_NAME=test_db),这个 hostname 就彻底失效。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 删掉
config/database.php中所有硬编码的数据库参数值,只保留env('DB_HOST', '127.0.0.1')这类兜底写法 - 确认
connections数组下每个连接名(如mysql)的字段都包裹env(),包括'type'、'database'、'username'等 - 若某字段没在
.env定义,又没设默认值(如env('DB_PORT', 3306)),运行时会报Undefined index
哪些配置项必须显式移除或禁用
'pool' => true、'persistent' => true、'params' => [PDO::ATTR_PERSISTENT => true] 这三类配置在 FPM 模式下不仅无效,还会干扰连接生命周期,导致大量 Sleep 连接堆积。TP8 的 Db::connect() 在 FPM 下每次都是新 PDO 实例,框架根本不处理连接复用。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 从
config/database.php中彻底删除'pool'相关键,它对 php-fpm 无意义 - 删掉
'persistent' => true—— 这是 mysqli 驱动专有配置,TP8 默认用 PDO,写了也忽略 - 若手动加了
'params' => [PDO::ATTR_PERSISTENT => true],请改为[PDO::ATTR_PERSISTENT => false]并确认 PHP 版本 ≥ 8.1,否则可能触发连接泄漏
.env 中哪些变量名是非法的
TP8 解析 .env 时严格按大写下划线匹配,DB_PASSWORD 有效,db_password、DB_PASS、DBPWD 全部无效。更隐蔽的是:含特殊字符(@、/、:、%)的密码未 URL 编码,会导致 DSN 解析断裂,报 Connection refused 而非认证失败。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 用
php -r "echo rawurlencode('pa@ss/word');"手动编码密码,结果填入.env,如DB_PASS=pa%40ss%2Fword - 检查
.env文件是否带 BOM 头(Windows 记事本易产生),可用file -i .env或 VS Code 底部编码栏确认,必须为 UTF-8 无 BOM - 删掉所有注释行开头的
#后多余空格,TP8 的DotEnv解析器对格式敏感,# DB_HOST=127.0.0.1会被跳过,但DB_HOST=127.0.0.1 # comment是合法的
移除后如何验证是否真生效
改完配置不等于连得上。TP8 的错误信息常掩盖真实原因,比如 SQLSTATE[HY000] [2054] 看似 MySQL 报错,实际是 PHP 驱动不认认证插件;Access denied 可能是 .env 密码未编码,也可能是 MySQL 用户 plugin 没切到 mysql_native_password。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 先跑原生验证脚本:
test_db.php里用new mysqli('127.0.0.1', 'root', 'pa%40ss%2Fword', 'test_db', 3306),确保底层通 - 执行
php think run后访问任意页面,看日志里是否出现Connected to MySQL(需开启verbose) - 查
runtime/log/sql/下最新日志,若 SQL 日志为空但 APP_DEBUG=true,说明数据库配置根本没加载成功,回退检查.env变量名和config/database.php的env()调用链
真正难的不是删配置,而是删完之后——你得知道哪一行没删干净,或者哪个环境变量名拼错了,而框架不会告诉你。



















