composer 不感知其他工具生成的依赖变更,必须显式执行 composer require 或安全修改 composer.json 并运行 composer update --lock 同步锁文件,否则会导致 vendor/ 与声明不一致、ci 构建失败等问题。

直接说结论:Composer 本身不感知、也不主动同步其他工具生成的依赖变更;composer.json 必须由人或明确脚本维护,否则极易出现 vendor/ 与声明不一致、composer.lock 失效、CI 构建失败等问题。
为什么 composer install 不会自动补全缺失的 require 条目
Composer 的设计原则是「声明即契约」:composer.json 是唯一可信源,vendor/ 只是它的执行结果。即使你手动把某个包(比如 guzzlehttp/guzzle)丢进 vendor/,或者用脚本生成了类文件并修改了 autoload,composer install 仍只会按 require 字段拉取——它不会反向扫描 vendor/ 并更新声明。
- 常见错误现象:CI 环境执行
composer install报错Class not found,但本地运行正常——大概率是本地手动cp过包,而composer.json没写require - 使用场景:用
phpstan或psalm扫描出新依赖、用脚本批量生成 SDK 客户端、从旧项目迁移时直接复制vendor/ - 正确做法:发现缺失依赖后,必须显式执行
composer require vendor/package-name,而不是跳过这步
如何让脚本生成的依赖写入 composer.json
没有通用 hook,但可通过组合命令实现自动化注入。关键点是避免手写 JSON,防止格式错误或字段覆盖。
- 用
composer require --no-install先写入composer.json而不下载包(适合 CI 前预处理) - 若需批量添加,可用
jq工具安全修改 JSON:jq '.require["myorg/sdk"] = "^1.2"' composer.json > tmp.json && mv tmp.json composer.json
- 修改后务必运行
composer validate校验语法,再执行composer update --lock同步锁文件 - 注意:不要用
echo >> composer.json直接追加,JSON 格式会被破坏,composer后续命令会报JSON decode error
与其他工具协作时最容易被忽略的坑
很多团队在接入代码生成器(如 OpenAPI Generator)、静态分析工具或 monorepo 管理器(如 Lerna + PHP 子包)时,只关注产出物,却漏掉 Composer 的契约完整性。
-
composer.lock不会自动重算:哪怕composer.json被脚本改了,不跑composer update --lock,composer.lock里还是旧版本,部署时可能拉错包 - 开发环境和生产环境行为不一致:本地用
composer require装了包,但脚本生成的composer.json没提交,Git 里就少了这一行 - autoload 映射不同步:脚本生成的类若放在非标准目录(如
gen/),光改require不够,还得同步更新autoload.psr-4并执行composer dump-autoload -o
最常被绕过的动作是「验证并提交 composer.lock」——只要 composer.json 变了,composer.lock 就不再是可选文件,而是必须跟上且纳入 Git 的事实标准。跳过这步,等于把依赖一致性交给运气。











