直接运行composer why vendor/package-name可查该包被谁直接依赖,仅显示显式声明的上游,不穿透replace/provide或require-dev;为空则可能是历史残留或间接依赖。

查某个包为什么被装进 vendor
直接运行 composer why vendor/package-name,比如 composer why guzzlehttp/psr7。它会告诉你当前项目里谁显式声明了这个依赖——只显示直接上游,不展开间接链。输出类似:
laravel/framework v10.48.12 requires guzzlehttp/psr7 (^2.4)
这说明 Laravel 框架本身 require 了它;如果输出为空,大概率是历史残留,没被任何活跃依赖链引用。
注意:composer why 不查 dev 依赖(如 phpunit/phpunit),也不穿透 replace 或 provide 关系(比如 illuminate/support 常被 laravel/framework 替代,why 就查不到)。
想看完整引用路径用 --tree
composer why --tree vendor/package-name 会展示一条从你项目根到目标包的依赖链,比如:
myapp/myproject<br>└── laravel/framework v10.48.12<br> └── symfony/console v6.3.4
但它只返回**一条路径**(通常是最高优先级那条),不是所有可能路径。真要查“所有引用者”,得用 composer depends --tree vendor/package-name(Composer 2.5+)。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
常见误判点:
- 拼错包名(
monolog≠monolog/monolog) - 包名含斜杠但 shell 未加引号(
zsh或 Windows 下推荐写'doctrine/dbal') - 锁文件里没装这个版本,却查
composer why vendor/package:2.9.1→ 报Package not found
为什么查不到某些包?
三种典型情况:
-
composer why illuminate/support返回空:因为它是 Laravel 内部组件,被laravel/framework通过replace声明替代,why默认不穿透这类关系 - 包只在
require-dev里(如phpunit/phpunit):默认不显示,加--no-dev才能排除干扰,或明确用composer why --dev vendor/package - 包被私有源、git repo 或 path repository 安装:
why只处理标准 Packagist 风格依赖,对非标准源无响应
此时可补查 composer show -t | grep package-name 看是否真被锁定了,或翻 composer.lock 搜索确认存在性。
别把它当万能溯源工具
composer why 解决的是「谁声明了我」,不是「谁在代码里用了我」。它完全不扫描 PHP 文件里的 use、new、配置项或服务提供者注册。删包前必须人工验证:
- 用
grep -r 'GuzzleHttp\' app/ config/搜硬编码调用 - 检查
config/app.php的providers和aliases - 跑
php artisan tinker手动new GuzzleHttpClient()确认是否还可用
最常被忽略的一点:即使 why 显示某包只被一个 dev 工具引用,它也可能在生产环境被配置文件里的字符串类名间接触发 autoload —— 这种隐式依赖,why 根本看不到。

















