composer unused 不是 composer 内置命令,需用第三方工具如 composer-unused 进行 ast 静态分析;它支持 php 8.1+,推荐 phar 安装,需排除 tests/、vendor/ 等目录,并人工验证结果。

composer unused 不是内置命令,运行会报错
直接在项目里敲 composer unused 或 composer check-unused,一定会失败——Composer 本身压根没提供这类命令。它只管按 composer.json 装包、更新、解析依赖树,从不扫描你的 .php 文件里有没有 use 或 new。所谓“检测未使用包”,必须靠第三方工具做 AST 静态分析。
推荐用 composer-unused(不是 roave/dependency-analyser)
roave/composer-dependency-analyser 曾经流行,但近年维护变慢,对 PHP 8.2+ 的 readonly 属性、枚举构造函数等支持不稳定;而 composer-unused 是目前最活跃、准确率更高的一线方案:它用 php-parser 真实解析语法树,能识别类名、函数调用、常量、甚至配置数组里的字符串键名(比如 ['driver' => 'redis'] 中的 redis 可能暗示用了 predis/predis)。
- 安装推荐 PHAR 方式,避免本地依赖冲突:
curl -OL https://gitcode.com/gh_mirrors/co/composer-unused/releases/latest/download/composer-unused.phar && chmod +x composer-unused.phar - PHP 版本要对得上:v0.12.x 要求 ≥ PHP 8.1;若项目还在 PHP 7.4,只能用
v0.9.11,否则直接报ParseError: syntax error, unexpected token "readonly" - 别漏掉排除目录:默认会扫
tests/、vendor/、var/,导致误判“某包只在测试里用”,应加--exclude "tests/*" --exclude "vendor/*" --exclude "var/*"
结果要人工二次判断,不能照单全删
工具输出的“未使用包”只是线索,不是判决书。比如:
-
monolog/monolog没被use或new,但可能被框架通过 PSR-3 接口自动注入,删了就炸 -
ext-gd这类扩展依赖,composer-unused完全不检测,得自己查composer.json里的"ext-gd": "*"声明,或运行时调extension_loaded('gd') - 配置文件(如
config/packages/cache.yaml)里写了doctrine/doctrine-bundle相关项,但没直接引用类——这种需手动加--additional-files="config/**/*.yaml"
删之前务必跑一遍全量测试 + 检查生产配置
确认某个包真没用,步骤是:先在 composer.json 的 require 或 require-dev 里删掉对应行 → composer update --dry-run 看是否影响其他包 → composer update 实际卸载 → ./vendor/bin/phpunit 全量跑测试 → 再检查部署脚本、CI 流水线里有没有硬编码依赖该包的逻辑(比如 Dockerfile COPY 了某个 vendor 下的 bin 工具)。
最容易被忽略的是:有些包只在 bin/ 目录下提供 CLI 工具(如 php-cs-fixer),代码里没引用,但部署流程依赖它——这种不会出现在 AST 分析里,得翻 CI 配置和运维文档。










