核心是用COMPOSER_HOME+全局config.json统一vendor路径:设环境变量指向自定义COMPOSER_HOME,在其config.json中配置"vendor-dir"为共享目录,所有项目install/update均写入该目录;项目级config.vendor-dir无效,手动symlink vendor会导致autoload失效。

多项目共享 Composer 依赖,核心不是“复制 vendor”,而是让多个项目指向同一套已安装的包——否则每次 composer install 都重复下载、解压、生成 autoload,既慢又浪费磁盘,还容易因环境差异导致行为不一致。
用 COMPOSER_HOME + 全局 config.json 统一 vendor 路径
这是唯一被 Composer 官方支持的跨项目 vendor 共享方式。它不改每个项目的 composer.json,而是通过环境变量接管所有项目的安装目标目录。
- 先设置环境变量:
export COMPOSER_HOME="/opt/my-composer-home(Linux/macOS)或set COMPOSER_HOME=C:\my-composer-home(Windows) - 在该目录下创建
config.json,内容为:{"config": {"vendor-dir": "/opt/shared-vendor"}} - 确保
/opt/shared-vendor目录存在且当前用户有读写权限 - 之后所有项目执行
composer install或composer update,都会把包装进/opt/shared-vendor,而非各自vendor/
⚠️ 注意:vendor-dir 写在项目级 composer.json 的 config 字段里完全无效——Composer 明确忽略它。
为什么不能直接 symlink 各项目的 vendor/?
手动 ln -s 会导致 autoload 失效或类加载冲突,因为 Composer 生成的 autoload_files.php 和 autoload_classmap.php 是基于项目根路径硬编码的。共享 vendor 必须由 Composer 自己驱动,而不是靠文件系统层面的软链。
- 每个项目仍需保留自己的
vendor/autoload.php入口文件(Composer 会自动生成) - 但该文件实际加载的是
/opt/shared-vendor/composer/autoload_real.php,再由它分发到各包的真实路径 - 若强行替换
vendor/为软链,composer dump-autoload可能报错,phpstan等工具也会因路径错乱无法解析类型
path 类型仓库不适合多项目共享,别把它当“本地 npm link”
很多人想用 "type": "path" 把一个本地包链接给多个项目,这在语义和实现上都是反模式。
-
path仓库本质是开发调试机制,要求被引用包的composer.json中声明"options": {"symlink": true},且只在composer update时生效 -
composer install不重建 symlink,CI 环境通常禁用 symlink,导致构建失败 - 多个项目 require 同一个 path 包时,版本号必须严格匹配其
name和version字段,稍有不一致就报Could not find package - 真正需要共享的包,应发布为私有 Git 仓库 + Packagist 镜像(如 Satis),或走全局 vendor 方案
最易被忽略的一点:全局 vendor-dir 方案下,composer.lock 仍需按项目提交——它记录的是「哪些包被装进了共享目录」,不是「装在哪」。删掉 lock 文件再 install,可能拉取新版,破坏多项目间的一致性。











