composer install会删包是因为它严格按composer.lock同步,若lock中无该包,install便清除vendor中残留;它不解析composer.json变更,仅还原lock快照,确保环境一致。

不是 install 删了你的包,而是 install 严格按 composer.lock 执行同步 —— 如果 lock 文件里没它,install 就会把它从 vendor 里清掉。
composer install 为什么会删包
执行 composer install 时,Composer 不看 composer.json 里写了什么,只忠实还原 composer.lock 记录的依赖快照。如果你手动删过 composer.json 里的某行依赖、但没运行 composer update 更新 lock 文件,那 lock 里还存着这个包的记录;可一旦你用其他方式(比如 composer remove 或直接编辑 lock)让 lock 文件丢失了该包,再跑 install,它就会把 vendor 里残留的对应目录整个删掉。
- 常见诱因:改了
composer.json后忘了composer update,就直接git pull拉了别人更新过的 lock 文件 - CI 环境中有人提交了没生成 lock 的变更,导致下游
install按旧 lock 还原,但本地 vendor 有“多余”包 -
composer update --lock被误用:它只重写 lock 文件,不碰 vendor,但后续install会立刻清理 vendor 中 lock 未声明的包
怎么确认是不是 lock 导致的误删
先对比 lock 和 vendor 的实际状态:
- 查 lock 里有没有:
grep -A 5 '"vendor/package-name"' composer.lock - 查 vendor 里还在不在:
ls vendor/vendor-name/package-name - 查当前生效的依赖树:
composer show vendor/package-name—— 如果报 “not found”,说明 lock 已剔除它
如果 lock 里没有、vendor 里却有,那就是 install 在“纠错”:它在强制对齐 lock 快照,不是 bug,是设计行为。
为什么不能跳过 lock 直接按 json 安装
composer install 本身不解析 composer.json 的依赖变更 —— 这是故意的。lock 文件保证多人协作、CI 构建、生产部署时依赖完全一致。想按最新 composer.json 重新算依赖,必须用 composer update,而不是 install。
- 误操作示例:删了
composer.json里的monolog/monolog,直接composer install→ vendor 里 monolog 还在(因为 lock 没变) - 正确流程:删 json 条目 →
composer update monolog/monolog --with-dependencies(或全量update)→ lock 更新 →install才会真正删 vendor - 风险点:直接
rm -rf vendor && composer install看似重来,但如果 lock 文件陈旧,可能装回旧版甚至冲突版本
删包后 vendor 还残留?那问题不在 install
如果执行完 composer install,某个包仍在 vendor 里,但 lock 和 json 都已移除它,说明根本没删干净 —— 很可能是 composer remove 中断、或手动删了 json 却没触发 update,导致 lock 文件残留了该包的哈希记录。这时 install 反而会把它拉回来。
- 验证方式:
composer show vendor/package-name若仍显示已安装,说明 lock 里还有它 - 安全清理:先
composer remove vendor/package-name(自动更新 lock),再composer install - 硬核手段:手动删
composer.lock里对应包的整段 JSON(含 name/version/dist/hash),再composer install—— 但极易出错,仅限调试
真正容易被忽略的是 lock 文件的“隐性权威性”:它不声不响决定 vendor 的生死,而开发者往往只盯着 composer.json 看。











