composer show --who 是首选命令,它直接从 installed.json 和 composer.lock 中精确匹配 require 字段,不依赖实验配置、不忽略 provide、不受 replace 干扰,输出仅含直接依赖者,支持 --no-dev 和虚拟包,2.2+ 版本开箱即用。

直接用 composer show --who,不是 composer depends,也不是 composer why —— 后两者要么已弃用、要么行为不稳定、要么默认不显示完整路径。
为什么 composer show --who 是首选
它从 vendor/composer/installed.json 和 composer.lock 中真实读取每个已安装包的 require 字段,逐个比对是否包含目标包名,不依赖实验配置,不跳过 provide 声明,也不受 replace 干扰。
- 输出干净:只列“谁直接 require 了它”,比如
laravel/framework、monolog/monolog - 加
--no-dev可排除require-dev中的包,避免误判生产环境依赖 - 不需提前启用任何 experimental 配置,
composer self-update到 2.2+ 即可用 - 对虚拟包(如
psr/log)也有效 —— 它查的是实际安装包的require,不是 Packagist 元数据
composer why --tree 适合溯源,但容易漏掉源头
当你想知道“这个包最终是从我自己的 composer.json 哪里进来的”,composer why --tree 才是关键。它会向上追溯完整路径,直到顶层项目。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 不加
--tree:只返回第一层,比如laravel/framework,但你看不到它是不是被你项目直接 require 的 - 加
--tree:输出类似monolog/monolog └── laravel/framework └── your-project-name dev-main,末尾的your-project-name才是真正源头 - 如果某行结尾带
[dev],说明该路径来自require-dev;若中途断在某个包名后没继续,大概率是那个包用了"provide": {"psr/log": "*"} - 必须确保
vendor/已存在且composer.lock有内容,否则报Could not find package
当 composer show --who 返回空,别急着删包
空结果 ≠ 没人用它。常见真实原因是:
- 该包是通过
provide虚拟声明的(例如psr/log),而提供者本身没在require字段写它 —— 此时得用composer show --tree | grep -B1 -A1 "psr/log"手动翻找 - 它只装在
require-dev里,但你运行时加了--no-dev或环境变量COMPOSER_NO_DEV=1 - 包名拼错:
monolog/monolog不能写成Monolog/monolog或monolog,斜杠和小写必须完全一致 - 它被
replace规则移除了(比如用your-org/logger替换了monolog/monolog),此时composer show --who查不到原包名,但composer show --tree仍能看到替代者
真正复杂的地方在于:Composer 不区分“逻辑依赖”和“物理安装”。一个包可能没出现在任何 require 字段里,却因 provide 被当成接口实现加载进来 —— 这时候靠命令行查不到,得看代码里 use 了哪个命名空间,再反推是谁注册了那个 autoloader。

















