改了config/database.php仍连不上数据库,是因为.env中db_host等键会全量覆盖对应连接配置块,而非字段级合并;且需确保.env在项目根目录、utf-8无bom、变量名全大写下划线、密码url编码,并清除runtime/config.php缓存。

.env 优先级高于 config/*.php 文件,但前提是它被正确加载且变量名匹配、格式合法。
为什么改了 config/database.php 还连不上数据库?
因为 .env 中定义的 DB_HOST、DB_NAME 等键会全量覆盖 config/database.php 中对应连接的整个配置块——不是字段级合并,而是整块替换。哪怕你只写了 DB_NAME=test,框架也会丢弃 database.php 里 'hostname'、'username' 的原始值,只保留 env() 能读到的部分。
-
.env必须放在项目根目录(与app/、config/同级),且编码为 UTF-8 无 BOM - 变量名必须全大写+下划线:
DB_PASS有效,db_pass或DB_PASSWORD无效 - 含
@、/、:的密码必须手动 URL 编码,例如pa@ss/word→pa%40ss%2Fword - 修改
.env后不清理缓存,runtime/config.php仍用旧值,连接行为不会变
CLI 命令下 .env 根本不生效的常见原因
ThinkPHP 8.0 默认只在 Web 入口(public/index.php)加载 .env,CLI 模式(如 php think migrate)完全跳过这一步——不会报错,也不会提示,只是静默忽略。
- 必须在项目根目录的
think文件末尾手动添加:\Dotenv\Dotenv::createImmutable(__DIR__)->safeLoad(); -
__DIR__必须指向项目根目录,不是public/或vendor/ - 定时任务要用
cd /path/to/project && php think xxx,不能直接调用public/index.php -
Env::get('DB_HOST')返回null?很可能是白名单限制,改用env('DB_HOST', '127.0.0.1')更可靠
APP_ENV 和 config/{env}/ 目录的关系
.env 里的 APP_ENV=prod 本身不触发环境切换——它只是个普通变量。真正起效的是系统级环境变量或入口文件中显式设置的 APP_ENV,框架据此加载 config/prod/ 下的同名 PHP 配置文件,再用 .env 覆盖其中字段。
-
APP_ENV必须小写,且严格匹配子目录名:prod有效,production或PROD无效 - Nginx/FPM 中推荐用
fastcgi_param APP_ENV prod;透传,比依赖.env更稳定 -
config/prod/下至少得有app.php(哪怕内容是空数组),否则框架不加载该目录 -
config/database.php里不能写死值,所有字段都得用env('DB_HOST', '127.0.0.1'),否则生产环境会沿用开发默认值
最容易被忽略的一点:.env 加载失败时几乎不报错,你看到的“配置没变”大概率是它根本没被读到;而 runtime 缓存不清,会让错误配置持续生效数小时甚至更久。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











