thinkphp 读不到 .env 数据库配置,主因是环境变量未加载:.env 必须位于项目根目录、php variables_order 含 e、无 bom、格式严格(等号无空格、特殊字符需引号)、配置文件中需显式调用 env() 并清缓存。

ThinkPHP 读不到 .env 里的数据库配置,不是密码写错了,而是环境变量压根没加载进来——90% 的情况是 .env 文件被静默跳过,框架退回到硬编码值或默认值,连错误提示都不会给。
为什么 env('DB_HOST') 返回 null 或空字符串
ThinkPHP 6+ 默认只在 Web 入口(public/index.php)中自动加载 .env,但这个“自动”有严格前提:
-
.env必须放在项目根目录(与app/、config/、public/同级),不是public/.env或config/.env - PHP 配置中
variables_order必须含E(即variables_order = "EGPCS"),否则$_ENV始终为空,getenv()也查不到 - TP8 默认用
Dotenv::createImmutable()->safeLoad(),遇到 BOM 或非法字节会直接跳过整文件,不报错 - 如果你在
bootstrap/app.php或配置文件里提前调了Env::get('DB_HOST'),此时.env还没加载,必然返回null
.env 格式错一个字符就全失效
vlucas/phpdotenv 解析器对格式极其敏感,出错即静默跳过,不会警告也不会报错:
- 等号两侧绝对不能有空格:
DB_PORT=3306✅,DB_PORT = 3306❌(整行被忽略) - 密码含
@、%、!、$等字符必须加双引号:DB_PASSWORD="abc@123%"✅,DB_PASSWORD=abc@123%❌(@后被截断) - 文件必须是 UTF-8 无 BOM 编码;Windows 记事本默认带 BOM,会导致
safeLoad()直接失败 - 注释只能独占一行且以
#开头,DB_HOST=127.0.0.1 # local这种行末注释会解析失败
配置文件里没调 env() 就等于没写
只在 .env 里写 DB_HOST=192.168.1.100 是无效的,必须显式在配置中引用:
- 修改
config/database.php,把'hostname' => '127.0.0.1'换成'hostname' => env('DB_HOST', '127.0.0.1') - 所有字段都要这样替换,包括
password、database、prefix等,第二个参数不能为空(建议用''而非null) - 不要在控制器里补救式调
env('DB_HOST')——配置加载只发生在初始化阶段,之后改也没用 - 改完必须清缓存:
php think clear:config或删掉runtime/config.php
CLI 和 Swoole 下 .env 完全不走默认流程
运行 php think migrate 或 Swoole 服务时,.env 默认不加载,因为入口不是 public/index.php:
- TP8 CLI 模式需在项目根目录下的
think文件末尾手动加:if (PHP_SAPI === 'cli') { \Dotenv\Dotenv::createImmutable(__DIR__)->safeLoad(); } -
__DIR__必须指向项目根目录(含composer.json的那一层),不能是public/或vendor/ - 定时任务要写成
cd /path/to/project && php think schedule:run,不能直接调用/path/to/public/index.php - 验证是否生效:在命令中执行
dump(getenv('DB_HOST')),看输出是否和.env一致
最易被忽略的是缓存和编码——哪怕格式全对,runtime/config.php 里还存着旧值,或者 .env 里藏着一个看不见的 BOM,都会让整个配置链路失效。动手前先 file -i .env 看编码,再 php think clear:config 清缓存,比反复检查密码有用得多。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











