composer remove 卸载包会自动移除声明、清理 vendor、更新 lock 文件并重建 autoload,失败则回退;不加 --no-update 时默认重装,加则需手动 update;它能识别 require 或 require-dev 区域,但不处理间接依赖和代码残留。

用 composer remove 卸载包,不是删文件,是删声明+同步清理
它会自动从 composer.json 的 require 或 require-dev 中移除条目、删除 vendor/vendor-name/package-name 目录、更新 composer.lock、重建 autoload 映射——整个过程原子化,失败即回退。
- 不加
--no-update时,默认执行完整重装;加了就只改composer.json,后续得手动跑composer install或composer update - 它能自动识别包在哪个区(
require还是require-dev),比如phpunit/phpunit装在require-dev里,直接composer remove phpunit/phpunit就行,不用加--dev - 如果包被其他已安装包硬依赖(比如
symfony/http-client明确 requireguzzlehttp/guzzle),命令会中止并提示“required by another package”,这不是报错,是保护机制
删完还有残留?先别手删 vendor/,检查这三处
常见错误现象:运行 composer remove monolog/monolog 后,vendor/monolog/monolog 看似没了,但 composer show monolog/monolog 还能查到,或代码里 new MonologLogger 仍能运行——多半是 autoload 缓存或路径残留没清干净。
- 强制刷新自动加载:
composer dump-autoload -o - 清 Composer 自身缓存:
composer clear-cache(尤其之前用过镜像源异常或--no-cache) - 检查
composer.json的autoload.files或autoload.psr-4是否还硬写了该包路径(remove不动这些)
想清间接依赖?不能靠 remove 一步到位
composer remove 只处理顶层声明的包,不会主动删它的子依赖。比如删了 guzzlehttp/guzzle,psr/http-message 可能还在——因为 symfony/http-client 也在用它。
- 确认某个子依赖是否真没人要:
composer why psr/http-message,输出为空才是“孤儿” - 若确定上游包也不需要了,可用
composer remove guzzlehttp/guzzle --with-dependencies,让 Composer 连带清理“只被它引用”的依赖(如guzzlehttp/promises) - 慎用
--no-update后再手动update:容易遗漏冲突,锁文件哈希错乱风险高,CI 构建可能失败
卸载只是第一步,代码里的残留它不管
composer remove 不会动你 PHP 文件里的 use、new、配置项、服务提供者注册、数据库迁移、缓存键……这些全得人工扫。
- 全局搜索类名:
grep -r "Monolog\" . --include="*.php"(注意反斜杠转义) - 检查
config/下的配置文件(Laravel/Symfony 项目常见)、app/Providers/里的服务注册 - 运行核心功能或自动化测试,验证是否真没影响——尤其
require-dev里那些调试工具,删了可能让本地开发卡住
composer why 和 composer show 这两个命令,比想象中更关键。










