composer-unused是当前最可行的检测手段,它不依赖autoload或require声明,而是反向扫描php源码中use、new等真实调用痕迹,再结合人工验证配置、注解和运行时加载。

直接结论:别信眼睛扫 use,也别只看 composer.json;用 composer-unused 扫代码调用痕迹,再人工验证配置、注解和运行时加载,才是靠谱路径。
为什么 composer-unused 是当前最可行的检测手段
它不依赖 autoload 配置或 require 声明,而是反向扫描你的 PHP 源码(src/、app/、config/ 等),查找真实存在的 use、new、class_exists()、interface_exists() 等调用痕迹。这比 composer show --tree 或 composer depends 更贴近“真正在用”的定义。
常见误操作包括:
- 没跑
composer install就执行composer unused→vendor/不全,结果漏报 - 默认跳过
tests/目录 → 若包只在测试里用(如phpunit/phpunit),会被标为“冗余”,但你不该删 - 没加
--scan-tests或--exclude=vendor→ 扫到 vendor 自身源码,干扰判断 - 项目用了
bin/console或artisan入口文件,但没把它们加入扫描路径 → 工具看不到命令类注册逻辑
composer-unused 容易误报的三类包,必须人工核对
静态分析无法覆盖运行时行为,以下情况常被标红,但删了会出事:
-
symfony/polyfill-*:即使没use,也可能被laravel/framework或symfony/console在低版本 PHP 下悄悄 require;删掉直接Fatal error: Uncaught Error: Call to undefined function mb_strlen() -
psr/container、psr/simple-cache:Laravel/Symfony 的契约接口,框架内部通过 DI 容器反射加载,代码层几乎不显式use - 注解驱动的包(如
doctrine/annotations)或配置驱动的扩展(如topthink/think-queue在config/queue.php里写死的'handler' => \think\queue\connector\Redis::class):工具扫不到字符串里的类名
验证方法:全局搜 'Some\Class'(带单引号)、"Some\Class"、class_alias、app()->bind、ServiceProvider::register,再检查 config/ 和 app/Providers/。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
删包前必须搞清:谁在拉它?它还剩不留?
执行 composer remove 前,先确认这个包是否已被其他依赖“绑定”。否则会失败或残留:
- 报错
Package "monolog/monolog" is not required in your composer.json→ 它是传递依赖,得先查源头:composer why-usage monolog/monolog(Composer 2.4+)或composer depends monolog/monolog(旧版) - 输出为空 → 真孤儿,可删;若显示
laravel/framework和guzzlehttp/guzzle都在拉它 → 删前得评估影响面 - 删完后
vendor/还有目录?正常。Composer 只改composer.json和composer.lock,物理删除要靠后续composer install或composer update同步 - 想彻底清理残留?确保
composer.json已删干净,再删composer.lock,最后composer install—— 仅限开发环境
清理后 vendor 依然臃肿?可能是 autoload 陷阱在作怪
一个包体积大,不代表你用了全部功能。比如 monolog/monolog 的 PSR-4 映射覆盖整个 src/,哪怕你只 use Monolog\Logger,Composer 仍会把所有 handler、formatter 加进 autoloader classmap。
这不是冗余依赖问题,而是 autoload 精细化配置缺失:
- 检查
composer.json的autoload和autoload-dev,删掉已不存在的psr-4路径(如废弃模块的映射) - 避免用
classmap整目录扫描,改用精确路径或files加载必需函数文件 - 运行
composer dump-autoload -o后,打开vendor/composer/autoload_classmap.php,确认里面没有已删除包的类路径
真正难处理的从来不是“哪个包该删”,而是“它被谁以什么方式加载”——动态类名、DI 注入、配置字符串、模板引擎里的类引用,这些都绕不开人工交叉验证。










