应使用 composer remove 卸载包,它自动更新 composer.json、删除 vendor 目录、同步 composer.lock 并重建 autoload 映射;手动删 vendor 或改 composer.json 会导致 autoload 错乱、类找不到、锁文件不一致及 CI 构建失败。

直接用 composer remove,别手动删 vendor/ 或硬改 composer.json —— 否则 autoload 错乱、CI 构建失败、类找不到都是大概率事件。
为什么不能手动删 vendor 目录或 composer.json 条目
手动删 vendor/monolog/monolog 再删 composer.json 里那行,最后跑 composer install,看似干净,实则埋雷:
-
composer.lock文件没更新,哈希校验失败,CI/CD 流水线可能直接中断 -
vendor/autoload.php仍保留旧的映射,use MonologLogger还能“成功”加载(缓存或残留 PSR-4 规则),但上线后报Class not found - 子依赖(如
monolog/monolog带来的psr/log)可能滞留vendor/,变成幽灵包,干扰后续composer update
composer remove 的正确用法和参数差异
composer remove 是 Composer 2.2+ 内置命令,不是脚本封装,它执行的是原子化反向安装流程:
- 自动识别包在
require还是require-dev中,无需加--dev(除非同名包同时出现在两个区) - 删
composer.json条目 → 删vendor/vendor-name/package-name→ 更新composer.lock→ 重建autoload_*.php - 不支持批量卸载:
composer remove a/b c/d会报错,必须逐个执行 - 想跳过实时重装?加
--no-update:只改composer.json,后续统一composer update(慎用,易漏冲突)
遇到 “Package is required by another package” 怎么办
这不是错误,是 Composer 在拦你。比如执行 composer remove guzzlehttp/guzzle,但 symfony/http-client 明确 require 它,Composer 就会中止并列出引用者。
- 先查依赖链:
composer why guzzlehttp/guzzle,看清谁在用、为什么用 - 若上游包(如
symfony/http-client)也确实不需要,按提示确认移除;或升级到不依赖 Guzzle 的新版 - 临时调试可加
--with-dependencies连带清理“只被该包引用”的子依赖(如guzzlehttp/promises) - 绝对避免先删
composer.json条目再composer install,锁文件和实际目录极易脱节
删完还要人工检查三处关键残留
composer remove 只管声明和 autoload 配置,不管你的代码是否还活着:
- 全局搜
use和new:grep -r "use Monolog\" . --include="*.php"(注意反斜杠转义) - 检查配置文件:
config/logging.php(Laravel)、config/packages/monolog.yaml(Symfony)等是否还引用该包 - 确认服务提供者:
app/Providers/或config/app.php是否注册了对应ServiceProvider - 额外验证:
composer show monolog/monolog应报 “Package not found”,ls vendor/monolog应提示 “No such file or directory”
最常被忽略的是 autoload 配置残留和 OPcache 缓存 —— 即使 vendor 清空、composer.json 改掉,vendor/autoload.php 里没删干净的 PSR-4 映射,或者 PHP 没清 OPcache,照样 Class not found。


















