ThinkPHP的.env文件需在初始化早期由think\initializer\Env::init()加载一次,仅限根目录、格式严格(无空格、全大写下划线)、受前缀白名单限制,修改后须清配置缓存才生效。

ThinkPHP 的 .env 文件不是“放进去就自动生效”,它是一套有明确加载时机、路径约束和解析规则的环境变量注入机制,核心在于 think\Env 类如何与 PHP 原生环境交互。
.env 文件只在初始化早期加载一次
框架仅在 App::init() 阶段(通常是入口文件 public/index.php 执行时)调用 think\initializer\Env::init() 加载一次 .env。此后无论你怎么修改文件或手动改写 $_ENV,都不会重新解析。
- 必须确保
.env位于项目根目录(与app/、config/、public/同级),不是放在config/或runtime/下 - 若已在 CLI 或 Web 服务器中通过
export APP_ENV=dev或fastcgi_param APP_ENV dev设置了APP_ENV,框架将跳过.env读取,直接使用该值 - Swoole、多进程等长生命周期场景下,仅主进程加载一次,Worker 进程不会重复加载,也不能自动同步变量
变量名和格式有严格要求
.env 的解析由 vlucas/phpdotenv(TP6+ 默认集成)完成,对空格、引号、大小写极为敏感:
- 等号两侧绝对不能有空格:
DB_HOST=127.0.0.1✅,DB_HOST = 127.0.0.1❌(整行被忽略) - 值含空格、特殊字符(如
@、!、/)必须用单引号包裹:DB_PASSWORD='pass@123!'✅ - 变量名区分大小写且必须全大写 + 下划线:
api_timeout无效,API_TIMEOUT才可被识别 - 注释只能用
#开头,前面不能有空格;不支持行末注释
env() 函数不是万能读取器
env('KEY') 并非直接读取 $_ENV['KEY'],而是经过白名单过滤和前缀校验:
立即学习“PHP免费学习笔记(深入)”;
- 默认只允许读取以
APP_、DB_、CACHE_、LOG_等预设前缀开头的变量 - 若要用
REDIS_URL,需提前追加前缀:think\Env::setPrefix(['APP_', 'DB_', 'REDIS_']); - CLI 模式下,系统环境变量优先级高于
.env:若已执行export REDIS_URL=redis://prod,env('REDIS_URL')返回的就是该值,不是.env里的 - 配置文件中用
{env:DB_HOST}占位符,仅在配置加载阶段由think\Config解析,且不支持运算或嵌套
配置缓存会让 .env 修改“看起来没生效”
ThinkPHP 会把所有 PHP 配置文件(包括 database.php 中通过 env() 读取的结果)合并写入 runtime/config/ 缓存。因此:
- 改完
.env后,必须清缓存才能让新值进入最终配置:php think clear:config或手动删除runtime/config/目录 - 开发时可临时关闭缓存,在
config/app.php中设'config_cache' => false - 若
database.php中某项未提供默认值(如'password' => env('DB_PWD')),而.env里又没定义该变量,就会传入null,导致连接失败



















