必须运行 composer update 才能使 composer.json 中新增/删除包、修改版本号、调整 stability 或 repositories 等变更生效,因为 install 仅按 lock 文件还原 vendor,不响应 json 变更。

不运行 composer update 会导致依赖不一致
手动改了 composer.json(比如增删 require、调整版本号、修改 repositories),只是“声明了意图”,Composer 并不会自动同步这些变更到 vendor/ 目录或 composer.lock。实际加载的类、函数、文件路径,全由 vendor/ 里的代码决定——而它和 composer.lock 才是运行时的真实依据。
composer install 和 composer update 的根本区别
这两个命令行为完全不同,不能互相替代:
-
composer install:只读取现有composer.lock,按锁文件精确还原vendor/。即使你改了composer.json,只要lock没变,它就当没看见 -
composer update:重新解析composer.json,重新计算依赖树,更新vendor/,并重写composer.lock - 如果你删了一个包但只跑
install,那个包仍留在vendor/里,autoload 依然能加载它——这会掩盖问题,甚至引发冲突
哪些修改必须触发 composer update?
不是所有改动都需要,但以下情况跳过 update 就等于没生效:
- 新增或删除
require/require-dev中的包(如加了"phpunit/phpunit": "^10") - 修改已有包的版本约束(如从
"guzzlehttp/guzzle": "^7.2"改成"^7.5") - 更改
minimum-stability或prefer-stable,影响版本选择逻辑 - 添加或修改
repositories(比如指向私有 Packagist),否则 Composer 根本找不到新源
反例:只改 name、description、autoload 的 psr-4 映射路径(且未执行 composer dump-autoload)——这类改动不涉及依赖安装,但也要单独处理。
容易被忽略的关键点
很多人以为改完 composer.json 跑一次 update 就万事大吉,其实还有几个硬性条件:
-
composer.lock必须可写,否则update会失败并报错Could not write lock file - 如果项目用了
composer install --no-dev部署,而你在require-dev里加了东西,update时得显式加--with-all-dependencies或确保 dev 包被纳入计算 - CI/CD 流程中,若先
install再改json再update,很可能因缓存导致旧 lock 文件残留,建议清理vendor/和composer.lock后重来
composer update guzzlehttp/guzzle --with-all-dependencies
这条命令只更新指定包及其传递依赖,比全量 update 更可控,适合线上小范围调整。
最常出问题的地方,其实是改了 composer.json 却忘了提交 composer.lock —— 它才是团队协作中依赖一致性的唯一权威来源。










