APP_ENV必须由系统环境变量设置,.env中的APP_ENV=prod无效;框架依据系统级APP_ENV值(如dev、prod)加载config/{env}/目录配置,并用.env文件覆盖对应项,需UTF-8无BOM编码、清缓存生效。

APP_ENV 必须由系统环境变量设置,不是 .env 里的值
ThinkPHP 不会读 .env 文件里的 APP_ENV=prod 来决定加载哪个环境配置——那行只是个普通变量,完全无效。真正起作用的是 PHP 启动前的系统级环境变量 APP_ENV,它决定了框架去加载 config/prod/ 还是 config/dev/ 目录下的配置文件。
常见错误现象:.env 里写了 APP_ENV=dev,但页面不显示调试信息、日志还是 error 级别——说明框架压根没加载 config/dev/app.php,因为 APP_ENV 实际是空或默认 production。
- CLI 模式下(如
php think run):Linux/macOS 执行APP_ENV=dev php think run;Windows 用set APP_ENV=dev && php think run - Nginx + PHP-FPM:在 server 或 location 块中加
fastcgi_param APP_ENV dev; - Apache:用
SetEnv APP_ENV dev - Docker:启动容器时加
-e APP_ENV=prod
.env 文件只做「覆盖」,不决定环境目录
.env 的作用是在环境配置加载完成后,对已合并的配置进行最终覆盖。比如 config/dev/database.php 定义了 'hostname' => '127.0.0.1',而 .env 里写了 DB_HOST=192.168.10.100,那么最终生效的是后者。
注意:.env 必须放在项目根目录(与 app/、config/ 同级),且编码必须是 UTF-8 无 BOM——否则 ThinkPHP 会静默忽略,不报错也不加载,这是最常被忽略的致命点。
立即学习“PHP免费学习笔记(深入)”;
- 等号两侧不能有空格:
DB_PASSWORD='p@ss#123'✅,DB_PASSWORD = 'p@ss#123'❌ - 含空格或特殊字符的值必须用单引号包裹
- 敏感字段(如密码、密钥)务必加到
.gitignore,避免提交到仓库
config/{env}/ 目录不能少,也不能命名错
ThinkPHP 6+ 和 8.0 的多环境本质是「目录隔离」:框架先加载 config/app.php,再根据 APP_ENV 值(必须小写、严格匹配)加载同名子目录下的对应文件,例如 APP_ENV=prod → 加载 config/prod/app.php 和 config/prod/database.php。
如果删掉 config/prod/,或者把目录命名为 production、PROD、Prod,框架就会 fallback 到基础配置甚至报错,根本不会识别为生产环境。
- 目录名必须全小写,且与
APP_ENV值完全一致 - 每个子目录下只需放差异项,比如
config/prod/database.php只写数据库主机、端口等变更项,不用复制全部键 -
config/根目录的 PHP 配置文件是兜底层,所有环境都共享
改完配置后必须清缓存,否则旧值还在用
ThinkPHP 会把合并后的最终配置缓存到 runtime/config.php。哪怕你改了 .env、改了 APP_ENV、也重启了服务,只要没清缓存,框架就继续读旧缓存——导致一切修改看起来“不生效”。
每次部署或本地切换环境后,必须执行:
-
php think clear:config(清除配置缓存) -
php think optimize:config(重新生成优化缓存) - 手动删掉
runtime/cache/和runtime/config.php也有效
最容易被忽略的是:CI/CD 流水线里没加这两条命令,上线后配置还是开发环境的;或者 Nginx 用的是旧 runtime/ 目录,导致新配置永远进不去。



















