composer本身不解析.env文件,仅支持在config.variables声明后、extra字段中通过${var}插值,变量来源为shell环境而非.env文件,且需显式导出。

Composer 本身不解析 .env 文件
Composer 是 PHP 的依赖管理工具,不是运行时环境,它不会自动加载或解析 .env 文件。你看到的 composer.json 中类似 ${DB_HOST} 这样的写法,只有在特定条件下才生效——它依赖于 Composer 的 variables 替换机制,且仅作用于 extra 字段,不能用于 require、autoload 或其他核心字段。
常见错误现象:在 composer.json 里写 "url": "${API_URL}",执行 composer install 后发现值没替换,甚至报错 Invalid argument supplied for foreach() 或直接忽略变量。
- 只有
extra下的键值会被变量替换,且必须启用config.variables - 变量来源仅限于 shell 环境(
export API_URL=https://api.example.com),不是.env文件 - PHP 的
getenv()或$_ENV不参与此过程,Composer 不调用它们
config.variables 怎么配才生效
要在 composer.json 中使用变量替换,必须显式声明 config.variables,并确保对应环境变量已导出。这个配置告诉 Composer:“这些变量名允许被引用,且从 shell 环境读取”。
示例:
{
"config": {
"variables": {
"API_URL": "https://localhost:8000",
"APP_ENV": "dev"
}
},
"extra": {
"api-url": "${API_URL}",
"env": "${APP_ENV}"
}
}
- 如果 shell 中执行了
export API_URL=https://prod.example.com,那么${API_URL}就会被替换成该值 - 未设置的变量会 fallback 到
config.variables中定义的默认值(如上例中的https://localhost:8000) - 变量名区分大小写,
api_url和API_URL是两个不同变量 - 不能嵌套,
${${FOO}}或${BAR:-default}都不支持
想读 .env 文件?得靠外部工具
Composer 没有内置的 .env 解析器。如果你习惯用 vlucas/phpdotenv,它只在 PHP 运行时起作用,对 composer.json 的解析毫无影响。真要让 Composer “感知” .env,只能靠构建前预处理。
典型做法是用 shell 脚本或 Makefile 加载 .env 并导出变量,再调用 Composer:
# load-env.sh set -a source .env set +a composer install
-
set -a让source .env中的变量自动 export 到子进程(即 composer) - 确保
.env格式为KEY=VALUE,不支持引号包裹的值(KEY="val"会导致解析失败) - Windows 用户需改用 PowerShell 或 WSL,原生 cmd 不支持
source - CI/CD 中(如 GitHub Actions)要显式
env:块注入变量,不能依赖.env文件自动加载
替代方案:用脚本生成动态 composer.json
当变量逻辑复杂(比如根据 APP_ENV 切换整个 repositories 或启用不同插件),硬靠 config.variables 会力不从心。更可控的方式是用 PHP 或 Node.js 脚本读取 .env,生成临时 composer.json,再执行安装。
例如用 PHP 快速生成:
<?php $env = parse_ini_file('.env');
file_put_contents('composer.json', json_encode([
'repositories' => [
['type' => 'composer', 'url' => $env['COMPOSER_REPO'] ?? 'https://packagist.org']
],
'require' => ['monolog/monolog' => '^2.0']
], JSON_PRETTY_PRINT));
- 适合 CI 流水线中多环境差异化依赖场景
- 注意生成的文件权限和 git 忽略(加
composer.json.dynamic到.gitignore) - 别在生产部署中直接覆盖主
composer.json,容易引发冲突
真正难的不是“怎么读”,而是厘清变量作用域:shell 环境变量 → Composer 变量替换 → PHP 运行时 getenv() → 应用配置层。这四层各自独立,混用就会踩坑。











