thinkphp 6+ 通过 app_env 环境变量控制多环境配置加载,优先读取 config/app_env/ 下对应文件并合并主配置;.env 中 app_env 才是环境开关,非 app_debug;nginx 需透传 fastcgi_param app_env $app_env;.env 不得提交至 git,生产环境由运维手动创建。

如何通过 APP_ENV 控制 ThinkPHP 多环境加载不同配置
ThinkPHP 6+ 默认靠 APP_ENV 环境变量决定加载哪个配置目录,不是靠域名或 IP 判断。它会优先读取 config/<code>APP_ENV/ 下的同名文件(比如 database.php),再合并到主配置里。
常见错误是直接改 .env 里的 APP_DEBUG=true 就以为切换了环境——其实没用,APP_ENV 才是开关。
-
APP_ENV=develop→ 加载config/develop/目录下的配置 -
APP_ENV=production→ 加载config/production/ - 未设置或值为空时,默认走
config/根目录(不推荐) - 确保
runtime目录可写,否则环境切换后缓存不会自动重建
为什么 .env 文件在生产环境必须被忽略
.env 是运行时环境变量入口,但它的内容(尤其是数据库密码、密钥)绝不能提交到 Git。一旦泄露,等于交出服务器钥匙。
典型误操作:本地开发完直接把带敏感信息的 .env 上传到线上,或者用 git add .env 同步。
- 立刻执行
echo ".env" >> .gitignore并提交 - 线上部署时,由运维手动创建
.env,只填必要项:APP_ENV=production、APP_DEBUG=false、DB_PASSWORD=xxx - 不要在
.env里写死APP_URL或ASSET_URL,它们应由 Nginx/Apache 的fastcgi_param或容器环境注入
config/develop/database.php 和 config/production/database.php 怎么差异化写
两个文件结构完全一致,只改关键字段。ThinkPHP 不支持「条件判断式配置」,所以别试图在一个文件里用 if (APP_ENV === 'develop') —— 它还没读到环境变量就报错了。
示例差异点:
-
'hostname' => '127.0.0.1'(开发) vs'hostname' => 'db-prod.internal'(生产) -
'debug' => true(开发) vs'debug' => false(生产) -
'prefix' => 'dev_'(开发库表前缀隔离) vs'prefix' => 'prod_' - 生产环境务必删掉
'params' => ['PDO::ATTR_EMULATE_PREPARES' => true],避免预处理失效
Nginx 配置里漏掉 fastcgi_param APP_ENV 会导致环境失效
CLI 模式下(如 php think optimize:config)能正确读取 .env,但 Web 请求走 FPM 时,.env 不会被自动加载——除非你在 Nginx 的 location ~ \.php$ 块里显式传参。
这是最隐蔽的坑:本地测试一切正常,一上 Nginx 就回退到默认配置。
- 必须加这一行:
fastcgi_param APP_ENV $app_env; - 然后在 server 块顶部定义:
set $app_env production;(生产)或set $app_env develop;(开发) - 别用
fastcgi_param APP_ENV "develop";这种硬编码,不利于多站点共存 - 验证是否生效:
var_dump($_SERVER['APP_ENV'] ?? 'not set');放在控制器里看输出
环境变量不是开关,是路径索引;配置不是写一次就完事,是每次部署都要核对的契约。尤其注意 FPM 场景下 Nginx 侧的透传,这里错一点,整个环境隔离就形同虚设。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











