getenv()常返回false是因为Composer子进程不继承shell环境变量,且$_ENV默认为空;可靠方式是优先用getenv('COMPOSER_SCRIPT_VAR')或$_SERVER['COMPOSER_SCRIPT_VAR'],并确保变量带COMPOSER_SCRIPT_前缀显式注入。

getenv() 为什么经常返回 false
因为 Composer 启动的 PHP 子进程默认不继承 shell 环境变量,$_ENV 在现代 PHP 中默认为空(variables_order 不含 E),而 getenv() 仅在进程启动时已存在的变量上有效。你在终端执行 APP_ENV=prod composer run build,脚本里仍拿不到 APP_ENV——这不是 PHP 配置问题,是 Composer 没把父 shell 的环境透传进来。
可靠读取方式是组合判断:
- 优先用
getenv('COMPOSER_SCRIPT_APP_ENV')(需显式注入) - fallback 到
$_SERVER['COMPOSER_SCRIPT_APP_ENV'](Composer 自动塞进$_SERVER) - 绝不依赖
$_ENV,除非你确认php.ini开了variables_order = "EGPCS"
COMPOSER_SCRIPT_* 是唯一原生支持的注入方式
Composer 唯一原生识别并自动注入子进程的环境变量,必须带 COMPOSER_SCRIPT_ 前缀。比如你想让脚本拿到 APP_ENV=staging,就得这样调:
APP_ENV=staging COMPOSER_SCRIPT_APP_ENV=staging composer run-script deploy
注意两点:
- 左边的
APP_ENV=staging只影响当前 shell,对 Composer 无意义 - 右边的
COMPOSER_SCRIPT_APP_ENV=staging才会被 Composer 捕获并注入到 PHP 脚本环境 - 大小写敏感:
COMPOSER_SCRIPT_app_env≠COMPOSER_SCRIPT_APP_ENV
composer.json 里 ${VAR} 占位符只在特定字段生效
composer.json 支持 ${VAR_NAME} 语法,但不是所有字段都认。它只在明确文档标注「支持变量插值」的位置起作用,比如:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
config.http-basic:可写"username": "${GIT_USERNAME}" -
repositories[].url:如"${PRIVATE_REPO_URL}" -
config.process-timeout:值必须是数字字符串,如"${COMPOSER_TIMEOUT:-300}"(但 fallback 由 shell 展开,Composer 本身不解析:-)
常见误用:
-
config.repos或require字段里写${FOO}—— 完全无效,不报错也不替换 - 把密钥写死在
composer.json里,哪怕只是测试值,也极易误提交
.env 文件和 phpdotenv 对 Composer 脚本无效
vlucas/phpdotenv 是给你的应用代码用的,不是给 Composer 自身用的。你在 index.php 里加载 .env,不影响 composer.json 里的 ${DB_HOST},也不影响 composer run-script 执行的 PHP 脚本——因为 Composer 进程启动时,autoload.php 还没加载,Dotenv::load() 更没运行。
如果非要让脚本读 .env,必须手动加在脚本开头:
require_once __DIR__.'/vendor/autoload.php';<br>Dotenv\Dotenv::createImmutable(__DIR__)->load();
但要注意:
- 路径必须准确,
__DIR__指的是脚本所在目录,不一定是项目根 - 默认只注入
$_SERVER,别指望getenv()或$_ENV能直接用 - CI/CD 中
.env文件通常不上传,应改用平台 secret 注入 +COMPOSER_SCRIPT_*透传
最易被忽略的一点:跨平台一致性。Windows CMD、Git Bash、Docker、GitHub Actions 对环境变量的继承规则完全不同,与其反复调试 shell 行为,不如统一约定用 COMPOSER_SCRIPT_* 前缀 + 显式注入,并在脚本里只信任 getenv() 或 $_SERVER。其他路径全是临时补丁,上线后容易崩。

















