手动修改 vendor 目录文件必然被 composer install/update 覆盖,因其是只读缓存且被 .gitignore 排除,导致修改无法版本控制、协作或 CI 验证;应优先提 PR、fork 替换、依赖注入或合规补丁方案。

vendor 目录不是你的代码编辑区
手动改 vendor 里的文件,等于在别人发布的包上直接动刀——下次 composer install 或 composer update 一跑,所有修改全丢。这不是“可能丢”,是设计上就注定会被覆盖:Composer 把 vendor 当作只读缓存,不保留任何本地变更。
你改的代码根本不会进版本控制
vendor/ 默认在 .gitignore 里,Git 根本不跟踪它。你花半小时修了一个第三方包的 bug,commit 推上去,队友拉下来后还是原始带 bug 的版本——因为你的修改没进仓库,也没法被 CI 检查或复现。
替代方案比硬改 vendor 更可靠
遇到包有缺陷或需要定制行为,优先走标准扩展路径:
- 提 PR 给上游仓库(哪怕只是先开 issue 描述问题)
- 用 Composer 的
repositories配置临时指向你 fork 后修复的分支 - 通过依赖注入、装饰器、事件监听等方式在应用层覆盖行为,而不是改底层实现
- 某些场景下可用
composer patch插件管理补丁,但需确保补丁可重放、可测试、可随升级自动失效
一个真实踩坑案例:patch 后忘记清理
有人为解决某个 HTTP 客户端超时问题,直接在 vendor/guzzlehttp/guzzle/src/Client.php 里改了默认超时值。上线后一切正常,两周后执行 composer update guzzlehttp/guzzle,新版本结构变动导致旧 patch 失效,composer install 报错并中断部署——因为 patch 工具试图把补丁打到已不存在的方法上。
patch: **** malformed patch at line 12: public function __construct(array $config = []) {这类问题不会在本地开发暴露,只在 CI 或新机器上爆发,且排查成本远高于一开始用配置或包装类解决。
真正难的不是改 vendor,而是让修改可持续、可协作、可验证。一旦绕过依赖管理机制,你就主动放弃了这些保障。










