直接结论:必须用composer-unused,它通过扫描php源码中use、new等真实调用痕迹识别未使用包;其他命令如composer show或grep均不可靠。

如何用 composer-unused 检测未被引用的包
直接结论:仅靠 composer show --installed 或手动 grep 代码无法可靠识别“无用包”,必须借助静态分析工具。最成熟、维护活跃的选择是 composer-unused。
它通过扫描项目中所有 PHP 文件(含 tests/ 和 vendor/ 中的 autoloaded 类,但默认跳过 vendor/),检查是否实际使用了每个已安装包导出的类、函数或接口。不是看 use 语句,而是看是否真有调用发生。
- 安装:
composer require --dev composer-unused/composer-unused - 运行:
vendor/bin/composer-unused - 首次运行建议加
--no-interaction --debug查看分析过程,避免误判(比如动态加载、注解驱动、配置文件引用等) - 注意:它默认不扫描
config/、routes/、resources/等非 PHP 目录,如有 YAML/JSON 配置依赖某包(如 Laravel 的spatie/laravel-permission在config/permission.php中被引用),需手动加--include config/**/*
为什么 vendor/bin/composer-unused 会漏报或误报
静态分析天然有盲区,composer-unused 不例外。它无法识别以下情况:
- 运行时反射调用(如
class_exists('SomePackage\Helper')或new $className) - Doctrine 注解(
@ORMEntity)、PHPDoc 标签(@var SomePackage\Class) - 服务容器绑定(Laravel 的
$this->app->bind(...))、事件监听器注册(Event::listen(...)) - 环境变量或配置开关控制的依赖(如只在
APP_ENV=local时加载的调试工具包)
所以输出结果里标为 “unused” 的包,务必人工确认——打开它的 GitHub 主页看 README 是否说明了“仅配置生效”或“需手动启用”,再全局搜索包名在 config/、bootstrap/、app/Providers/ 下的出现位置。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
对比其他方案:why not composer why & composer-require-checker
composer why xxx 只能查某个包“为什么被装上”,不能反向列出所有可疑包;composer-require-checker 是检查 composer.json 声明的依赖是否全被代码引用,但它不处理自动加载机制、不支持排除路径、配置复杂,且对 PSR-4 自动发现支持弱。
-
composer why-not xxx不存在,别被名字误导 -
composer-require-checker需要手写require-checker.json列出所有入口文件,对 Laravel/Symfony 项目几乎不可行 -
composer-unused开箱即用,支持 Laravel/Symfony/WordPress 项目结构,默认忽略测试和 vendor,更适合日常瘦身
删包前必须验证的三件事
删掉一个标为 unused 的包后,项目不一定还能跑。执行 composer remove xxx 前,请确认:
- CI 流水线是否通过:尤其关注 phpunit、pest、phpstan、psalm 是否报错(某些包提供断言宏或类型定义)
- 运行时是否触发
Class 'XxxYyy' not found:重点测试命令行指令(php artisan/bin/console)、Web 请求入口、队列任务 - IDE 是否仍能正确跳转:比如删掉
laravel/telescope后,Telescope::record...调用可能还在 config/app.php 里,但 IDE 不再识别,容易后续遗漏清理
真正麻烦的从来不是检测,而是判断“这个包到底算不算业务依赖”——比如 ramsey/uuid 可能只在迁移文件里用了一次,但删掉会导致 php artisan migrate:fresh 失败;这种隐式依赖,得结合 git blame 和 commit message 一起看。










