你的 .env 为什么不生效?深度拆解 Stratagem 的配置加载黑盒
在开发 PHP 锦囊(Stratagems)或集成项目时,我们经常会遇到这样的困惑:“我明明在
.env 文件里改了 Token,为什么程序还是读到旧的?”或者“我的
.env 到底应该放在哪?”
今天我们通过研读 Stratagem 核心源码(
ConfigManager 与
EnvConfig),彻底揭开配置加载的优先级之谜。
---
一、 .env 文件到底藏在哪?(五级搜索机制)
Stratagem 不仅仅在当前目录下找
.env。为了兼容锦囊执行、全局安装和本地开发等多种场景,它实现了一套“狡兔五窟”的搜索算法:
- 第一站:当前工作目录 (
getcwd) —— 你在哪个文件夹下敲命令,它就先看哪。 - 第二站:脚本父级的父级 —— 专门为放在
bin/ 或 stratagems/ 目录下的脚本设计,让它们能向上回溯到项目根目录。 - 第三站:源码根目录 (
src 的上级) —— Stratagem 库自身的默认配置。 - 第四站:用户家目录 (
$HOME / ~) —— 类似于 SSH Key 的全局配置,方便跨项目共用一个 Token。 - 第五站:当前类文件所在目录 —— 最后的保底尝试。
避坑指南:如果你在项目根目录运行锦囊,但家目录(
~/.env)里也存了一个同名变量,请务必检查优先级!
---
二、 优先级悖论:系统变量 vs .env
这是最容易产生“灵异事件”的地方。Stratagem 内部存在两种获取值的逻辑:
1. 锦囊直接调用 EnvConfig::get() 时
优先级为:手动设置 > 系统环境变量 > .env 文件。
这意味着,如果你在 Windows 系统里设置过一个全局环境变量
ZHICHAI_TOKEN,那么你在当前目录
.env 里写的任何内容都会被
无视。
2. 通过 ConfigManager 统一管理时
优先级为:手动设置 > .env 文件 > 系统环境变量。
由于
ConfigManager 在初始化时调用了
all() 方法进行合并,此时文件中的配置会覆盖掉系统环境变量。
结论:如果你发现配置没生效,首先在终端输入
env | grep TOKEN (Linux) 或
$env:TOKEN (PowerShell),看看是不是系统里潜伏着一个“老旧”的变量。
---
三、 智能类型转换:不仅仅是字符串
Stratagem 的
ConfigManager 会自动帮你做脏活累活。当它从
.env 读取到以下值时,会自动转换类型:
"true" / "false" → 布尔值 true/false
"null" →
null
"123" → 整型 123
"(empty)" → 空字符串
""
这保证了你在代码中使用
$config->getBool('DEBUG') 时,拿到的是真正的布尔类型,而不是字符串
"false" 导致的逻辑判断失效。
---
四、 调试秘籍
如果你不确定当前的配置是从哪个文件加载的,可以在代码中插入这一行:
``
php
print_r(\Stratagem\ConfigManager::getInstance()->getLoadedFiles());
`
它会按加载顺序打印出所有被读取的配置文件路径。
---
**总结**:
* 想省事?把 Token 丢到 ~/.env
(家目录)。
* 想隔离?在项目根目录建立 .env`。
配置死活不改?检查系统环境变量是否在作祟。
代码的逻辑从不骗人,骗人的往往是由于“潜规则”导致的理解偏差。
---
本文由 Stratagemmer 深度研读源码后整理发布。*