绝大多数情况下必须重启PHP进程;因ThinkPHP仅在初始化时读取一次.env,后续全走内存缓存,不重启则env()始终返回旧值。

ThinkPHP改完.env必须重启PHP进程吗?
绝大多数情况下——要。不是“建议”,是硬性要求。ThinkPHP 的 env() 函数只在应用初始化阶段(入口文件首次执行时)读取一次 .env,之后全程从内存缓存中取值。改完文件后不重启,env('DB_HOST') 仍返回旧值,连 var_dump($_ENV) 都不会变。
哪些场景下看似不用重启,其实只是“假生效”
常见错觉来源:你在控制器里写了 echo env('APP_DEBUG');,刷新页面看到变了——但这只是因为 PHP-FPM worker 进程刚好被回收、新请求分配到了刚启动的进程。这不是热更新,是碰巧轮到了“干净”的进程。真实生产环境或长连接服务(如 Swoole/Workerman)中,这个行为不可控、不可靠。
- Swoole HTTP Server 启动后,
.env修改完全无效,必须kill -USR2或重启整个服务 - PHP-FPM 模式下,即使设置了
pm=ondemand,worker 进程默认存活数分钟,旧配置会持续影响新请求 - CLI 命令(如
php think queue:work)启动后也只读一次.env,中途改了得手动 stop + start
有没有真能不重启的办法?
有,但代价高、适用面窄。核心思路是绕过框架的静态配置加载机制,改为每次连接数据库/发请求前动态读取:
- 把数据库配置移到 Redis 或 JSON 文件里,用
Cache::get('db_config')替代config('database') - 自定义一个
Db::connectWithLatestConfig(),内部调用Dotenv\Dotenv::createImmutable(...)->safeLoad()再解析 - 仅适用于非核心配置(比如第三方 API 地址),且需自行处理并发读写、缓存失效等问题
对绝大多数项目,强行不重启反而增加维护复杂度和出错概率。
立即学习“PHP免费学习笔记(深入)”;
重启前必须做的三件事
光重启不够,漏掉任何一项都可能导致“明明改了还是没用”:
- 确认
.env在项目根目录(与app/同级),且是 UTF-8 无 BOM 编码 - 执行
php think clear:config或手动删掉runtime/config.php—— 否则框架直接读缓存,根本不碰.env - 检查是否被系统级环境变量覆盖:在控制器里输出
getenv('DB_HOST')和$_ENV['DB_HOST'],若前者有值后者为空,说明php.ini的variables_order没包含E
最常被忽略的是缓存清理。哪怕你重启了十次 PHP-FPM,只要 runtime/config.php 还在,它就永远按旧值运行。



















