Composer脚本中无法读取APP_ENV等环境变量,根本原因是子进程不继承父shell环境且$_ENV默认为空;唯一可靠方式是使用COMPOSER_SCRIPT_前缀变量,如COMPOSER_SCRIPT_APP_ENV=staging。

Composer 脚本里直接用 getenv('APP_ENV') 或 $_ENV['APP_ENV'] 读不到值,不是配置漏了,也不是 .env 文件写错了——是 Composer 启动的 PHP 子进程默认不继承 shell 环境变量,$_ENV 在现代 PHP 中也默认为空。
为什么 getenv() 在 Composer 脚本里总返回 false
根本原因有两个:getenv() 只能读取进程启动时已存在的环境变量,而 Composer 启动子进程时会清空大部分父 shell 的环境;同时 PHP 默认 variables_order 不含 E,所以 $_ENV 始终为空。你在终端执行 APP_ENV=prod composer run build,脚本里依然拿不到 APP_ENV,这不是 PHP 配置问题,是环境没透传过去。
- CI/CD、Docker、Windows 下尤其明显,因为这些环境对进程隔离更严格
-
export APP_ENV=prod后运行composer run-script deploy,变量不会自动进入脚本上下文 -
.env文件对 Composer 完全透明,它不加载也不解析,哪怕文件就在根目录下
可靠读取方式:只认 COMPOSER_SCRIPT_* 前缀的变量
Composer 唯一原生支持的环境变量注入机制,就是识别以 COMPOSER_SCRIPT_ 开头的变量,并自动将其注入到脚本子进程的 $_SERVER 和 getenv() 中。这是目前最轻量、最稳定、无需额外依赖的方案。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 想让脚本拿到
APP_ENV=staging,必须这样调:COMPOSER_SCRIPT_APP_ENV=staging composer run-script deploy - 脚本中应优先使用
getenv('COMPOSER_SCRIPT_APP_ENV'),fallback 到$_SERVER['COMPOSER_SCRIPT_APP_ENV'] - 不要尝试读
$_ENV['APP_ENV']或getenv('APP_ENV'),它们在 Composer 脚本中基本等于永远为false - 这个机制不依赖
phpdotenv,也不需要改php.ini,开箱即用
如果必须用 .env 文件,得靠 vlucas/phpdotenv 手动加载
Composer 本身不处理 .env,但你可以用 vlucas/phpdotenv 在脚本里自己加载。注意它默认只往 $_SERVER 写,不填 $_ENV,也不调用 putenv(),所以 getenv() 仍可能为空。
- 安装:
composer require vlucas/phpdotenv:^5.0(PHP ≥ 8.0)或^4.3(PHP 7.4) - 入口脚本顶部加:
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__); $dotenv->load(); - 之后统一用
$_SERVER['APP_ENV'],别依赖getenv('APP_ENV') - 路径必须准确:
__DIR__指向.env所在目录;若入口在public/,要传dirname(__DIR__)} - 多环境需手动指定文件名,例如:
Dotenv\Dotenv::createImmutable(__DIR__, ".env.{$env}"),且$env必须由外部(如系统变量或 CLI 参数)提供,不能从.env自己读
${VAR_NAME} 占位符只在特定配置字段生效
Composer 支持在 composer.json 的部分字段里用 ${VAR_NAME} 插值,比如 config.http-basic、repositories[].url,但它不是通用变量替换机制。
- 插值发生在 Composer 运行时,调用的是
getenv(),所以你仍得确保VAR_NAME是进程启动时就存在的(如通过COMPOSER_SCRIPT_VAR_NAME注入) -
scripts字段里的命令行不支持插值,"post-install-cmd": "echo ${APP_ENV}"会原样输出字符串,不会替换 -
autoload、require、extra等字段完全不解析${...} - 这个功能仅用于配置驱动行为,不能用来给自定义脚本传参
真正容易被忽略的点是:环境变量的“可见范围”在 Composer 里被切得很碎——shell 层、Composer 主进程、PHP 子进程、phpdotenv 加载后上下文,各自有一套变量空间。不明确区分这四层,就容易反复踩进“明明 export 了却读不到”的坑。

















