composer install 不重装已存在的 vendor 是因为它默认仅依据 composer.lock 文件安装,不解析 composer.json 的变更;即使删除 vendor 目录,只要 lock 文件存在,就只是复原而非重装。

composer install 为什么没重装已存在的 vendor
因为 composer install 默认只按 composer.lock 安装,不读 composer.json 的变更,哪怕你删了 vendor 目录,只要 composer.lock 还在,它就照着锁文件拉包——根本不是“重装”,只是“复原”。
- 常见错误现象:
vendor删了再composer install,结果某个包还是旧版,甚至版本号对不上composer.json - 真正触发“按
composer.json重新解析依赖树”的命令是composer update - 如果只想重装当前 lock 文件里的版本(比如修复损坏的 vendor),用
rm -rf vendor && composer install就够;但想“强制按最新规则重算依赖”,必须动update
composer update --force-reinstall 的作用和限制
--force-reinstall 不是“从头来过”,而是让 Composer 卸载再重装每个包(哪怕版本没变),用于修复因部分文件损坏、权限错乱或软链接残留导致的运行异常。
- 它不会改变版本号,也不会更新到新版本——
composer update --force-reinstall和composer update的区别,就像“换轮胎”和“换整车” - 常见使用场景:CI 环境中 vendor 权限混乱、Docker 构建时 symlink 失败、PHP 扩展升级后某些包的
autoload缓存失效 - 注意:PHP 7.4+ 的 Composer 2.x 支持该参数;Composer 1.x 不识别,会报错
Unrecognized option: --force-reinstall
彻底重置依赖:删 lock + update 的实际效果
真要“重置所有依赖包”,核心动作是删掉 composer.lock,再跑 composer update。这会让 Composer 忽略历史约束,完全按 composer.json 重新解析、求解、锁定新版本。
- 执行顺序必须是:
rm composer.lock && composer update;单独composer update不删 lock,等于白干 - 副作用明显:可能引入不兼容更新(比如 Laravel 9 升到 10,或 Symfony 组件跨大版本),线上环境慎用
- 若只想重装指定包(如修复
guzzlehttp/guzzle),用composer update guzzlehttp/guzzle --with-dependencies更安全
Windows 下路径/权限导致重装失败的典型卡点
Windows 用户常遇到 Could not delete ...: Permission denied 或 symlink(): Operation not permitted,这不是 Composer 逻辑问题,而是系统级限制。
- 默认 Windows 不允许普通用户创建符号链接,
composer install会退化为复制,但某些包(如phpunit/phpunit)的 bin 脚本依赖 symlinks,导致后续命令报错 - 解决方法:以管理员身份运行终端,或启用开发者模式(
Settings → Update & Security → For developers → Developer mode) - 另一个坑:
vendor在 OneDrive 或 WSL 挂载路径下,文件系统不一致会导致 hash 校验失败,表现为反复重装、composer update卡住不动
composer.lock 文件的存在本身——它不是备份,是权威;删它之前,最好先 git status 看一眼改了啥。










