composer show -t 能显示真实依赖来源,括号中标明“by x[y]”表示被x的y版本直接引入,但不反映间接约束收窄或replace/provide关系,需结合--dry-run -v验证完整解析链。

composer show -t 能看到真实依赖来源吗
不能直接看到 composer.lock 中已固定的版本,它只按 composer.json 的约束做理论求解。如果你刚改过 composer.json 但还没 composer update --lock,composer show -t 输出的版本可能和实际安装的完全不一致。
真正有用的是加包名过滤:运行 composer show -t vendor/package-name(比如 composer show -t symfony/console),输出中每行末尾括号里会标出“谁要求了它”和“用了哪个版本”,例如:
└─symfony/console[5.4.32] <strong>by laravel/framework[10.48.5]</strong>
如果同一包出现多次且版本不同(如 symfony/console 被 laravel/framework 和 phpunit/phpunit 分别拉入),就要检查它们各自声明的版本范围是否有交集——没交集就是冲突根源。
为什么 dependency tree 里看不到 replace/provide 关系
因为 composer show -t 不展开 replace 或 provide 声明。比如多个日志库都声明 "provide": {"psr/log": "^1.0"},树里只会显示它们自己,不会体现“谁在替代 psr/log”。这种关系必须手动查对应包的 composer.json 文件。
常见陷阱:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
monolog/monolog和knplabs/knp-snappy-bundle都提供psr/log,但其中一个锁死了 PHP 版本要求,另一个没声明,结果在 PHP 8.1 环境下解析失败 -
symfony/polyfill-*包常被用作provide,但它本身不显式出现在树中,容易误判为“没装上”
如何用 dependency tree 快速定位冲突包
重点不是看树有多深,而是找重复出现、版本跨度大、或带 omitted for conflict 标记的节点。Composer 2+ 的 show -t 默认不标冲突,得配合 composer update --dry-run -v 交叉验证。
实操建议:
- 先跑
composer update --dry-run -v,从输出里找含because的嵌套行,定位第一个拒绝理由(比如php ^7.2 || ^8.0但你用的是 8.1.0) - 再用
composer show -t vendor/conflicted-package看谁在拉它、拉了几个版本 - 若发现某包被两个父包以互斥范围拉入(如 A 要
^5.2,B 要^6.0),就只能二选一:升级较旧的父包,或用conflict显式阻止冲突版本
tree 输出里 “by X[Y]” 的括号内容可信吗
括号里的 by X[Y] 表示该包是被 X 的 Y 版本直接 require 的,这个信息是准确的;但它不反映间接传递路径中的约束收紧行为。比如 laravel/framework[10.48.5] 可能只写 "symfony/console": "^5.4",但它的子依赖 symfony/console 实际又要求 "symfony/event-dispatcher": "^6.0",这个二级约束不会出现在树的括号里。
所以不能只信括号,得结合 --dry-run -v 输出里完整的 because 链来看。最常被忽略的一点是:某个包看似只被一个父包拉入,但它自己的 composer.json 里对 PHP 或扩展的约束,可能比父包更严,最终导致整个解析失败。










