答案是运行composer why-not vendor/package:version定位阻塞链,输出倒序显示从根声明到深层包的完整约束路径,需用完整版本号且检查require-dev等隐形冲突源。

直接运行 composer why-not 查阻塞源头,别删 vendor 或 composer.lock —— 这只会让 Composer 重跑一遍失败逻辑,根本没定位到谁在封杀目标版本。
报 “don’t install xxx” 就立刻执行 composer why-not
错误信息里出现类似 don’t install guzzlehttp/guzzle:^7.5,马上执行对应命令:composer why-not guzzlehttp/guzzle:^7.5。输出是倒序链路,从最后一行(你 composer.json 的根声明)往上读,每行末尾的 (required by ...) 就是上一级约束来源。
- 输出为空?先检查
require-dev—— 它不会出现在根声明里,但会悄悄拉低依赖版本,比如phpunit/phpunit锁死sebastian/exporter,间接拖住symfony/console - 写
^7或7可能匹配不到元数据,必须写全guzzlehttp/guzzle:^7.5.0或guzzlehttp/guzzle:7.5.0 - 加
--dry-run验证改动是否真能解出路径,例如composer require laravel/framework:11.0.0 --dry-run,不改任何文件就能预判结果
用 composer show --tree 看真实依赖结构
composer.json 是你写的“愿望清单”,composer show --tree 才是 vendor/ 和 composer.lock 里的真实快照。它能暴露你根本没意识到的间接路径,比如某包标着 (locked to 5.4.42) 或 (replaced)。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
- 查某个包被谁引入:
composer show --tree | grep "symfony/console" - 过滤关键段:
composer show --tree monolog/monolog | grep -A5 -B5 "guzzlehttp/guzzle",确认是不是某条路径在强制降级 - 看到
(provided)或(replaced)?得去那个包自己的composer.json查replace字段,确认是否真能等价替代
升级或降级单个包必须带 --with-dependencies
composer update vendor/package 默认拒绝更新其子依赖,哪怕新版本根本跑不起来。这是最常踩的坑。
- 升版本:
composer update monolog/monolog --with-dependencies,只动它和直系依赖 - 降主版本(如从
guzzlehttp/guzzle:^8.0切回7.4.5):必须先在composer.json里写死"guzzlehttp/guzzle": "7.4.5",再跑composer update guzzlehttp/guzzle --with-dependencies - 错误写法:
composer update "monolog/monolog:^3"—— 引号 +^会让 Composer 自己找“最新兼容版”,不是你要的3.0.0 - 执行后立刻
git diff composer.lock,确认只有目标包及其直系依赖被改,没波及其他
别信缓存,也别手动改 composer.lock
哈希校验失败(hash verification failed)不是文件损坏,是 composer.lock 里记录的 dist.sha256 和当前镜像返回的包内容不一致。同步清理三样东西才有效:
- 删
vendor/和composer.lock(建议先备份:cp composer.lock composer.lock.bak) - 切回官方源:
composer config -g repo.packagist composer https://packagist.org/ - 清缓存:
composer clear-cache;若仍不行,手动删~/.composer/cache/repo/https---packagist.org/
Git 合并 composer.lock 冲突时,不要打开文件硬改 —— lock 文件是派生品,不是源数据。干净合并 composer.json 的 require 和 require-dev 块后,删掉 composer.lock 和 vendor/,再 composer update 重生成。










