composer remove 不会清理孤立依赖,因其仅按 composer.json 声明和依赖图谱移除显式引用的包及未被其他包复用的传递依赖,但无法识别代码中实际是否调用;而 composer-unused 通过扫描源码中的 use、类名等静态引用,精准定位未被任何代码或配置使用的冗余包。

composer remove 不会清理孤立依赖,必须用 composer-unused 插件扫描后手动确认删除。
为什么 composer remove 不能清掉“孤儿包”
执行 composer remove monolog/monolog 只删你指定的包,不会顺手干掉它带进来的、但当前项目已不再需要的子依赖(比如 psr/log)。Composer 的依赖解析逻辑只认 composer.json 和已安装包的 require 声明——只要某个包仍被至少一个已安装包 require,它就被认为“有用”,哪怕你的 src/ 里一行 use 都没有。
- 常见翻车:删了
spatie/laravel-backup,symfony/filesystem还在 vendor 里躺着,因为laravel/framework也 require 它 - 更隐蔽的是
symfony/polyfill-*类包:它们常被核心组件悄悄 require,手动删会导致 PHP 低版本下Fatal error -
composer show --tree能看到依赖树,但无法判断某叶子节点是否真被你的代码引用
用 composer-unused 安全识别冗余包
它扫描 src/、tests/、config/ 等目录里的 use 语句和类名字符串(不分析 class_exists() 这类动态加载),比对 composer.json 中所有 require 和 require-dev 条目,列出未被引用的包。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 先装插件:
composer require --dev composer-unused/composer-unused - 运行扫描:
composer unused,输出类似:psr/cache (not used)、phpunit/phpunit (not used in src/) - 重点看
required-by字段:如果返回空,说明没其他包依赖它;若非空,得用composer depends vendor/package-name再确认上游是谁 - 对
doctrine/annotations、phpstan/phpstan这类注解或静态分析工具依赖的包,别轻信扫描结果——它们可能通过注解隐式使用
删完之后必须人工检查的三处残留
composer remove 和 composer-unused 都只动 composer.json 和 vendor/,不会碰你的代码。以下地方不扫,上线必报错:
- 全局搜索包名关键词:
grep -r 'GuzzleHttp\' . --include="*.php"(注意命名空间反斜杠要转义) - 检查
config/app.php(Laravel)或config/services.php里的providers、aliases、driver配置项 - 运行
composer dump-autoload --classmap-authoritative强制刷新映射;Docker/CI 环境加-o参数:composer dump-autoload -o
不想装插件?试试轻量级筛查法
适合小项目或临时验证,精度不如 composer-unused,但不用额外依赖:
- 临时清空
vendor/,再跑:composer install --dry-run,观察哪些包没出现在安装列表里——说明当前项目没显式或隐式需要它 - 用
composer show --tree找“叶子节点”,再查谁在 require 它:composer depends psr/log;如果只返回刚删掉的包,那它大概率是孤儿 - 删掉
composer.json中已废弃的autoload.psr-4映射路径,避免 autoload 扫描冗余目录(比如"App\Tests\": "tests/"但 tests/ 目录已删)
真正难的不是删包,是确认“这个包到底有没有被用到”。动态加载、配置驱动、注解绑定这些场景,工具扫不出来,只能靠人眼+测试覆盖兜底。










