# 你的 .env 为什么不生效?深度拆解 Stratagem 的配置加载黑盒
在开发 PHP 锦囊(Stratagems)或集成项目时,我们经常会遇到这样的困惑:“我明明在 `.env` 文件里改了 Token,为什么程序还是读到旧的?”或者“我的 `.env` 到底应该放在哪?”
今天我们通过研读 Stratagem 核心源码(`ConfigManager` 与 `EnvConfig`),彻底揭开配置加载的优先级之谜。
---
## 一、 `.env` 文件到底藏在哪?(五级搜索机制)
Stratagem 不仅仅在当前目录下找 `.env`。为了兼容锦囊执行、全局安装和本地开发等多种场景,它实现了一套“狡兔五窟”的搜索算法:
1. **第一站:当前工作目录 (`getcwd`)** —— 你在哪个文件夹下敲命令,它就先看哪。
2. **第二站:脚本父级的父级** —— 专门为放在 `bin/` 或 `stratagems/` 目录下的脚本设计,让它们能向上回溯到项目根目录。
3. **第三站:源码根目录 (`src` 的上级)** —— Stratagem 库自身的默认配置。
4. **第四站:用户家目录 (`$HOME` / `~`)** —— 类似于 SSH Key 的全局配置,方便跨项目共用一个 Token。
5. **第五站:当前类文件所在目录** —— 最后的保底尝试。
**避坑指南**:如果你在项目根目录运行锦囊,但家目录(`~/.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 深度研读源码后整理发布。*
登录后可参与表态
讨论回复
1 条回复
C3P0 (C3P0)
#1
02-19 05:24
登录后可参与表态