必须用 composer why-not laravel/framework:11.0.0 定位阻断链,输出从下往上读,末尾“(required by …)”指明冲突源头;若为空则检查 require-dev 或版本号是否写错。

依赖冲突不是网络或缓存问题,是约束无法同时满足——必须用 composer why-not 定位阻断链,而不是删 vendor 或 composer.lock。
怎么快速定位谁在拦着你装某个版本
报错里出现 don’t install laravel/framework v11.0.0,别猜,直接问 Composer:composer why-not laravel/framework:11.0.0。输出是一条从底往上读的链路,最后一行是你 composer.json 里的声明,中间每行的 (required by) 就是提互斥要求的包。
- 如果输出为空,先检查是否漏了
require-dev——很多冲突来自phpunit/phpunit或mockery/mockery拖着老版sebastian/exporter,间接锁死symfony/console - 必须用完整版本号,比如
laravel/framework:11.0.0,写成11或^11可能匹配不到元数据,返回空不是没冲突,是查不到 - 加
--dry-run验证:例如composer require laravel/framework:11.0.0 --dry-run,不改任何文件就能看到是否真能解出路径
为什么 composer show --tree 比 composer.json 更可信
composer.json 是你写的“愿望清单”,composer show --tree 才是当前 vendor/ 和 composer.lock 的真实快照。它暴露你根本没意识到的间接路径,比如某包标着 (locked to 5.4.42),或者被 (replaced) 了却没在 composer.json 里体现。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 查某个包被谁引入:
composer show --tree | grep "symfony/console" - 过滤关键段看依赖关系:
composer show --tree monolog/monolog | grep -A5 -B5 "guzzlehttp/guzzle" - 看到
(provided)字样,得去那个包自己的composer.json里确认它到底提供了什么,不能只信表面名字
更新单个包时最容易踩的三个坑
全量 composer update 在依赖多的项目里极易触发 SAT 求解器卡死,升级一个包必须控制影响范围。
- 正确写法:
composer update monolog/monolog --with-dependencies—— 只动它和直系依赖;错误写法:composer update "monolog/monolog:^3"—— 引号 +^会让 Composer 自己找“最新兼容版”,不是你要的3.0.0 - 降级跨主版本(如从
guzzlehttp/guzzle:^8.0切回7.4.5),必须在composer.json里写死:"guzzlehttp/guzzle": "7.4.5",不能只写"^7.0" - 执行后立刻
git diff composer.lock,确认只有目标包及其直系依赖被改,没波及其他——否则说明--with-dependencies没生效,或有隐式约束在起作用
镜像、缓存、repositories 这三者怎么配合才不互相打架
换镜像不是为了解决冲突,而是让冲突暴露得更快更准。但 90% 的“换源无效”其实是配置没生效,静默 fallback 回 packagist.org。
- 镜像生效硬性条件:命令必须是
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/(注意-g、composer类型、结尾/);漏掉任一,composer config -g repo.packagist就返回空 - 只要
composer.json里有"repositories"字段(哪怕空数组),全局镜像就会被丢弃——不是合并,是直接忽略 - 换镜像后仍拉
repo.packagist.org,90% 是缓存没清干净:composer clear-cache必须做,怀疑 provider 同步滞后就加--refresh
真正难的不是命令怎么敲,而是理解 Composer 不会“智能妥协”——它只找一组满足所有约束的版本组合,找不到就拒绝。所以每个 conflict 字段、每个 require-dev 条目、每个 autoload 路径,都可能成为隐式约束点。最常被忽略的,是 require-dev 里那些测试工具悄悄带进来的旧版依赖,以及私有包中未显式声明却已生效的 conflict 规则。










