composer.json中的config项完全覆盖全局配置,非合并;bin-dir须在vendor-dir内或为绝对路径,否则静默回退;config不支持嵌套合并,缓存可能导致修改不生效。

composer.json 中的 config 项会**完全覆盖**全局配置,不是合并,也不是“优先级更高”这种模糊说法——它直接删掉同名键,只留项目里写的值。
为什么 composer config -l 显示的值和你预期不一致
常见现象:composer config -l 显示 bin-dir 是 bin,但 vendor/bin 下没生成可执行脚本;或设了 process-timeout 却没生效。
- 项目
composer.json里写了"bin-dir": "bin",就彻底屏蔽了全局的"bin-dir": "vendor/bin",哪怕你只想改一个字段 -
cafile、github-oauth这类字段,全局配置和项目配置都可能生效,但composer config -l显示的是最终合并视图,不告诉你来源 —— 实际行为可能依赖环境变量或插件 -
process-timeout在 Composer 2.2+ 已弃用,-l仍可能显示旧值,但它已不参与任何逻辑 - 敏感字段(如认证 token)默认只显示
***,不是没配,是被隐藏了
repositories 的顺序就是实际搜索顺序,不是“优先级配置”
Composer 查包时,按 repositories 数组从上到下逐个请求,**第一个返回匹配包的源就立刻锁定,后续源完全不查**。这不是“多级 fallback”,而是硬性中断。
- 想用私有 fork 覆盖
monolog/monolog?必须把对应vcs源放在repositories数组最前面 - 加了
{"packagist.org": false}只是禁用自动发现,不会阻止 Composer 在最后 fallback 到它 —— 必须显式声明所有需要的源,并确保 packagist.org 不在数组末尾隐式生效 -
type: "package"适合精确控制单个包,type: "vcs"适合动态拉 tag/branch;别用type: "composer"私有源兜底全部包,极易因版本元数据缺失导致回退到 packagist -
composer show -a vendor/package能看到实际解析到的源地址和版本来源,比猜靠谱
怎么临时绕过项目 config 测试全局行为
不能靠删 composer.json 的 config 段 —— Git 提交历史和协作成员都会受影响,且可能误删其他关键字段。
- 最轻量:用
COMPOSER=/dev/null composer install,它让 Composer 完全忽略项目composer.json(包括autoload、scripts),只走全局配置。仅适合纯 config 调试 - 更稳妥:新建一个最小
minimal.json,只含{"config": {}},再运行COMPOSER=minimal.json composer install - CI 场景需强制用全局
bin-dir?避免改项目文件,用COMPOSER_HOME=/tmp/composer-global composer install --no-plugins - 改完
composer config --global后,已有项目不会自动更新生效 —— 必须重新跑composer install或update
真正容易漏掉的是:某些字段(比如 vendor-dir 和 bin-dir)之间存在路径校验约束 —— 若 vendor-dir 是相对路径而 bin-dir 是绝对路径,Composer 会静默忽略 bin-dir 并退回默认值,连 warning 都不报。











