Composer多仓库配置需用JSON数组,按从左到右顺序查找,优先放稳定源;支持composer、vcs、path三类,认证信息须通过auth.json分离配置,且必须禁用packagist.org防污染。

Composer 支持在一个项目中同时配置多个私有仓库源,关键在于正确使用 repositories 数组,并理解其查找顺序、类型差异和认证机制——不是“堆一堆 URL 就行”,顺序错、类型混、认证漏,包就拉不下来。
怎么写 repositories 数组?必须用 JSON 数组,不能用对象
很多人复制网上示例时误用对象写法(如 {"foo": {"type": "composer", ...}}),这会导致 Composer 忽略部分仓库或行为不可预测。官方只保证数组顺序生效,且按从左到右依次查找包。
- ✅ 正确:用
[](JSON 数组),每个仓库是独立对象 - ❌ 错误:用
{}(JSON 对象),键名无序,Composer 可能跳过某些源 - ⚠️ 注意:
"packagist.org": false是特殊语法,必须放在数组里作为一项,不能塞进其他仓库对象内部
{
"repositories": [
{ "type": "composer", "url": "https://private-packagist.example.com" },
{ "type": "vcs", "url": "git@gitlab.company.com:team/sdk.git" },
{ "type": "path", "url": "../shared-lib" },
{ "packagist.org": false }
],
"require": {
"company/sdk": "^3.2",
"company/shared-lib": "dev-main"
}
}
vcs、composer、path 三种类型怎么选?看用途和协作阶段
类型选错,轻则安装失败,重则本地开发和 CI 行为不一致。它们不是互换的替代品,而是解决不同场景的问题:
-
vcs:适合正式维护的私有包,需走 Git 标签/分支版本控制;要求 SSH 密钥或 HTTPS Token 认证;每次composer install都会 clone 或 fetch -
composer:适合团队级私有 Packagist(如 Satis、Private Packagist);元数据集中管理,安装快、可缓存;需auth.json配 HTTP Basic 或 API Token -
path:仅限本地开发联调,比如边改 SDK 边测业务项目;加"options": {"symlink": true}可软链到源码,改完立刻生效;切勿提交到生产环境或 CI
认证信息放哪儿?auth.json 的位置和写法有严格约定
把密码或 Token 写进 composer.json 是高危操作,Composer 强制要求凭证分离。但放错位置等于没放——它只认两个路径:
- 项目根目录下的
auth.json(优先级高,适合单项目专用凭证) - 全局配置目录的
auth.json(Linux/macOS 是~/.config/composer/auth.json;Windows 是%APPDATA%\Composer\auth.json) - HTTP 类型(如私有 Packagist)必须用
"http-basic"字段;Git 的 HTTPS 地址也走这条路;SSH 地址(git@...)则依赖系统 SSH Agent,不走auth.json
{
"http-basic": {
"private-packagist.example.com": {
"username": "api",
"password": "pk_abc123def456"
},
"gitlab.company.com": {
"username": "gitlab-ci-token",
"password": "glpat-xyz789..."
}
}
}
为什么 composer require 找不到包?90% 出在顺序和作用域上
最常被忽略的是:Composer 查找包时,只在第一个匹配到的仓库中解析版本。如果 company/log 同时存在于 VCS 和私有 Packagist,而 VCS 在前但没打 tag,就会报 Could not find package company/log —— 它根本没往后看。
- 把最稳定、版本最全的源(通常是私有 Packagist)放在
repositories数组最前面 - 如果某个包只在特定仓库存在,确保它在数组中位置靠前,且该仓库确实包含该包的
composer.json和有效版本(如1.0.0tag 或dev-main分支) - 运行
composer show company/log -a可查看该包实际从哪个仓库加载;composer config --list | grep repo检查当前生效的仓库列表
多仓库不是叠加越多越好,而是要像路由表一样讲优先级、分职责。一个没配 "packagist.org": false 的私有 Packagist 项目,可能因为某次 composer update 意外从 packagist.org 装了同名但非预期的包——这种问题线上才暴露,调试成本极高。










