composer 不读取 .env 文件,其脚本运行在独立 cli 环境中,仅继承 shell 启动时已有的环境变量;需通过系统级变量(如 export app_env=dev)或 ci/cd 预设方式传递,而非依赖框架的 dotenv 加载。

composer install 时 $_ENV 为空或报 Undefined index
Composer 本身不读 .env 文件,也不会把环境变量注入到 PHP 运行时的 $_ENV 或 getenv()。你在 composer.json 的 scripts 里写 php -r "var_dump($_ENV['APP_ENV']);" 报错,不是代码写错了,而是执行上下文根本没加载这些变量。
- Composer 脚本运行在独立的 CLI 环境中,只继承 shell 启动它时已有的环境变量(比如你手动
export APP_ENV=dev过的) -
.env是 Laravel、Symfony 等框架在应用启动阶段用vlucas/phpdotenv加载的,和 Composer 完全无关 - 别试图在
post-install-cmd里用file_get_contents('.env')手动注入——路径不可靠、格式无校验、值未 trim、还可能泄露敏感信息
怎么让 composer install 阶段能用到 APP_ENV 这类变量
真需要在 install 时区分环境(比如加载不同配置),就得绕过 .env,改用系统级环境变量或 Composer 自身机制。
- CI/CD 中:提前在 pipeline 步骤里
export APP_ENV=production,再跑composer install - 本地开发:用
APP_ENV=local composer install(Linux/macOS)或set APP_ENV=local && composer install(Windows CMD) - 避免硬编码:scripts 里别写
echo $APP_ENV,改用php -r "echo getenv('APP_ENV') ?: 'default';"做兜底 - 更干净的做法:把环境判断逻辑移到
autoload.php或框架入口,让 Composer 只管装包,不碰配置
为什么比对 .env 和实际生效值总是不一致
因为变量来源不止一个,优先级混乱是常态。PHP CLI 的 getenv() 会按顺序查:系统环境变量 > putenv() > .env(如果某处显式加载了它)。
- 检查真实值:运行
php -r "print_r(getenv());",看输出里有没有你要的键 - 确认是否被覆盖:某些工具(如 Docker、Laravel Envoy)会在执行前 unset 或重设变量,
echo $APP_ENV在 shell 里有值,不代表 PHP 进程里也有 - 注意大小写:Linux/macOS 区分大小写,
APP_ENV和app_env是两个变量;Windows 不区分,但 PHP CLI 默认不继承小写变量 - 别信 IDE 终端显示:VS Code 内置终端可能缓存旧环境,关掉重开,或直接用系统 Terminal 验证
composer install 卡住后看到变量突然“变空”
这往往不是变量丢了,而是 Composer 换了进程上下文。比如它调用 git 克隆私有包时,子进程默认不继承全部环境变量(尤其 Windows 下),导致后续脚本里 getenv() 返回空。
- 验证方式:在 scripts 里加一行
env | grep APP_ENV(Linux/macOS)或set APP_ENV(Windows),看是否出现在输出中 - 临时修复:在
config段加"process-timeout": 0,并确保git命令本身可访问(PATH 正确) - 根治办法:放弃在 install 阶段依赖动态环境变量,把差异化逻辑下沉到
post-autoload-dump或应用初始化时
getenv() 的实际输出,比对着 .env 文件猜要快得多。











