答案是本地包的require、conflict等字段会完整参与全局sat求解,90%冲突源于其composer.json中php版本或依赖约束与项目不兼容;需用composer why-not vendor/local-package:dev-main定位,配合--stability=dev、删lock条目及--with-dependencies更新。

本地包(path repository)引发的版本冲突,90% 不是包写错了,而是 Composer 把它当成了“外部源”来解析约束,而你没意识到它的 require 会参与全局 SAT 求解。
composer.json 里加了 path repo,为什么 update 还报 don’t install?
Path 类型仓库本质是“本地镜像”,Composer 会完整读取它 composer.json 中的 require、conflict、replace 字段,并纳入整个依赖图计算。哪怕你只 require 了本地包的一个版本,它的子依赖也会被强制拉进来参与校验。
- 常见错误:本地包的
composer.json写着"php": "^7.4",但项目已升到 PHP 8.1 —— Composer 直接拒绝安装,哪怕代码本身兼容 - 另一个坑:本地包用了
"monolog/monolog": "^1.25",而项目主干要求^3.0,冲突就卡在 monolog 上,不是你的本地包本身 - 注意:path repo 默认不启用
minimum-stability降级,如果本地包有dev-main分支但没配"minimum-stability": "dev",Composer 就直接跳过它
怎么快速确认是不是本地包拖垮了依赖树?
别猜,用 Composer 自带命令反向定位:
- 运行
composer why-not vendor/local-package:dev-main(必须带完整分支名或 tag),看输出最上面一行是否指向你的 path repo 路径 - 如果输出为空,加
--stability=dev再试:composer why-not vendor/local-package:dev-main --stability=dev - 查真实依赖链:
composer show --tree vendor/local-package,重点看括号里有没有(locked to 1.2.3)或(replaced)—— 前者说明被 lock 文件锁死了旧版,后者说明它替代了别的包,可能引入隐性约束
本地包更新后 composer update 失败,该动哪几处?
本地包改了 composer.json 后,不能只跑 composer update,因为 lock 文件仍记着旧约束。必须显式触发重解析:
- 先删掉本地包在
composer.lock里的条目(搜索"vendor/local-package"手动删整段),再跑composer update vendor/local-package --with-dependencies - 如果它依赖的第三方包也变了,比如从
guzzlehttp/guzzle:^7升到^8,得同步检查项目里所有用GuzzleHttpClient的地方是否兼容 - 切忌用
composer update --ignore-platform-reqs绕过 —— 它不会修复本地包内ext-curl缺失这类真实问题,只会把报错延后到运行时
为什么 vendor/autoload.php 找不到本地包的类?
这通常不是版本冲突,而是 autoload 配置没生效。Composer 只在 composer dump-autoload 时读取本地包的 autoload 字段:
- 确保本地包的
composer.json里有正确autoload,例如:"autoload": {"psr-4": {"Vendor\LocalPackage\": "src/"}} - 改完后必须执行
composer dump-autoload,否则vendor/autoload.php不会包含它的映射 - 如果本地包用了
files加载方式(比如全局函数),要确认它没被composer.json根目录的autoload.files覆盖或忽略
本地包的路径和约束是透明参与求解的,没有“特殊豁免”。最易被忽略的是:你改了本地包的 composer.json,却忘了它现在是一个新约束源,而不仅仅是代码容器。











