composer show --tree 不能替代依赖解析诊断,因为它只显示已安装包的静态层级结构,无法反映依赖冲突、版本回退或解析过程中的决策路径;真正需要的是 composer update --dry-run -v 等命令输出的动态解析日志。

composer show --tree 为什么不能替代依赖解析诊断
composer show --tree 只展示当前锁文件中已安装包的层级结构,不反映依赖冲突、版本回退或解析过程中的决策路径。它看不到 Composer 实际尝试过哪些版本组合,也看不到为什么某个包没被升级——这恰恰是诊断的核心盲区。
真正需要的是 Composer 在 install 或 update 过程中“思考”的快照。官方为此提供了 --verbose 和专用诊断命令,但默认不启用,需主动触发。
用 composer update --dry-run -v 输出完整解析日志
这是最直接获取依赖解析行为的方式,--dry-run 防止实际修改 vendor 和 composer.lock,-v(或 --verbose)则强制输出 Resolver 的每一步推导,包括:候选版本筛选、约束匹配失败、回溯尝试、强制保留规则等。
- 运行
composer update --dry-run -v后,重点看以Reading composer.json开头、到Resolving dependencies through SAT(SAT 指布尔可满足性求解器)之后的大段日志 - 若出现
Skipped package ... because it's locked to version ...,说明composer.lock中存在硬性锁定,--dry-run仍受其约束;此时需加--ignore-platform-reqs或临时删 lock 文件验证假设 - 错误如
Conclusion: don't install laravel/framework v10.30.0后紧跟着十几行-> satisfiable by ...推理链,就是冲突根源所在,不要跳过中间行
composer depends 和 composer prohibits 的定位差异
composer depends 查“谁依赖我”,composer prohibits 查“谁阻止我装某个版本”,二者都是静态查询,不触发解析器,但能快速定位干扰源。
-
composer depends --tree monolog/monolog可看到哪些包(含间接依赖)把 monolog 拉了进来,及其传递路径 -
composer prohibits guzzlehttp/guzzle:7.8.0会列出所有与该版本冲突的 require 约束,例如spatie/laravel-backup 7.3.0 requires guzzlehttp/guzzle ^6.5 - 注意:
prohibits不检查 dev-dependencies,除非加--with-all-dependencies;而depends默认也不查 require-dev,需显式加--including-required
自定义 SAT 日志级别:设置 COMPOSER_MEMORY_LIMIT 和 COMPOSER_DISABLE_TTY
当依赖图复杂、解析超时或日志被截断时,底层 SAT 求解器的行为会被隐藏。这时需调整环境变量来暴露更底层信息:
- 设
COMPOSER_MEMORY_LIMIT=-1防止因内存不足提前终止解析(尤其在 CI 环境中常见) - 设
COMPOSER_DISABLE_TTY=1关闭交互式输出格式,确保-v日志完整写入管道或文件,避免 ANSI 控制符污染 - 结合重定向保存全量日志:
COMPOSER_DISABLE_TTY=1 composer update --dry-run -v 2>&1 | tee resolve.log,后续可用 grep 快速过滤Trying、failed、forced等关键词
真正卡住的地方,往往不是报错那一行,而是 SAT 在几十个版本间反复回溯却无法收敛——这种静默消耗,只有开全量日志+禁用 TTY 才看得见。











