composer-unused 不能完全准确识别未使用包,它通过静态扫描 PHP 文件中的 use、new 等调用比对 composer.json,但无法检测运行时加载、注解、DI 容器获取等场景,故存在误报。

composer-unused 能准确识别未使用的包吗
不能完全准确,但它是目前最实用的静态分析工具。它通过扫描 src/ 和 tests/ 目录下的 PHP 文件,检查 use 语句、new、static::、self::、parent:: 等调用,再比对 composer.json 中的 require 和 require-dev 列表,标记出“疑似未使用”的包。
注意:它不执行代码,也不解析运行时加载(如 class_exists()、Container::get()、字符串类名拼接),所以以下情况会被误报:
-
config/packages/*或services.yaml中引用的包(如 Symfony bundle) - 仅在注解(
@ORM\Entity)、PHPDoc(@var Some\Class)或测试断言中出现的类 - 通过 DI 容器动态获取、未显式
use的依赖(如 Laravel 的app(SomeService::class))
如何运行 composer-unused 并过滤误报
先全局安装(推荐):
composer global require composer-unused/composer-unused
然后在项目根目录执行:
composer-unused --no-progress --json
输出是 JSON 格式,便于脚本处理;加 --verbose 可看每个包被哪些文件“触发”过(帮助判断是否真不用)。常见过滤方式:
- 跳过
require-dev:加--exclude-dev(适合只想清理生产依赖) - 忽略特定包:用
--ignore=vendor-name/package-name(比如--ignore=phpunit/phpunit) - 限制扫描路径:用
--path=src(避免扫描tests/导致漏判) - 排除已知注解依赖:加
--ignore-annotations(跳过@开头的类引用)
composer show --unused 是 Composer 内置命令吗
不是。从 Composer 2.5 开始,官方仍没有提供 composer show --unused 这类内置功能。composer show 只能列出已安装包及其版本,不分析代码引用关系。所有“检测未使用依赖”的能力都来自第三方工具,主流就两个:
-
composer-unused:专注静态扫描,配置灵活,支持自定义路径和忽略规则 -
deptrac:更重架构分析,适合检查层间依赖违规,但对“包级废弃”不如前者直接
别被某些博客误导——搜索 composer show --unused 会返回 “Command 'show' is not defined.” 错误。
删掉包后为什么测试突然失败
因为有些包虽无直接 use,却是间接依赖链的一环。例如:
- 你删了
symfony/var-dumper,但phpunit的--debug模式内部用了它 - 你删了
psr/log,但monolog/monolog声明了该接口依赖,Composer 自动装了它;一旦手动删掉,Monolog 运行时报Class 'Psr\Log\LoggerInterface' not found -
composer dump-autoload后没清缓存,旧的 autoloader 还在引用已删类
安全做法是:删包前先跑 composer depends vendor/package 查谁依赖它;删完立刻执行 composer install --no-dev(模拟生产环境)+ 全量测试;别跳过 composer dump-autoload -o。
真正难判断的,永远是那些只在框架生命周期钩子、事件监听器或配置文件里“隐形存在”的包——它们不会出现在代码里,但删了就崩。这类得靠文档+经验+试错,工具帮不上忙。











