Composer 不支持自定义仓库 type(如 "myrepo"),仅内置 composer、vcs、package、artifact 四种类型;未知 type 会触发硬编码校验异常,且后续元数据读取与安装器均无对应实现;扩展协议需通过插件机制注入 VcsDriver 或劫持 RepositoryManager,而非修改 core 或 composer.json 中的 type。

Composer 不支持直接注册任意自定义仓库类型(比如 my-protocol),它只内置识别 composer、vcs、package、artifact 这几种 type。所谓“扩展仓库协议”,实际是通过 Composer 插件机制,在运行时注入对新协议(如 gitlab-ssh、http-tar)的解析和下载逻辑,而非修改 Composer 核心。
为什么不能直接在 composer.json 里写 "type": "myrepo"
Composer 的仓库加载器(RepositoryManager)硬编码了合法 type 值,遇到未知 type 会直接抛出异常:Invalid repository type [myrepo]。即使你绕过校验,后续的包发现、元数据读取、安装器匹配等环节都会失败——因为没有对应 RepositoryInterface 实现和 Installer 支持。
- 所有仓库
type必须是 Composer 内置枚举值之一 -
composer类型用于 Packagist 风格的 JSON 元数据服务(如私有 Satis / Private Packagist) -
vcs类型仅支持git、svn、hg等已注册 VCS 驱动,不接受自定义协议名 - 想让
https://my-repo.example/pkg.zip被当作独立仓库处理?必须用artifact类型,并确保路径指向 ZIP/TAR 归档文件
真正可行的“扩展”方式:用插件注入新协议处理器
Composer 插件(PluginInterface)可在 Plugin::activate() 中注册自定义 VcsDriver 或劫持 RepositoryManager 行为。典型场景是支持 GitLab 私有实例的 SSH URL(git@gitlab.example.com:group/pkg.git)或带认证头的 HTTP Git 仓库。
- 插件需声明
extra.installer-types(Composer 2.2+)或通过IOInterface注入驱动 - 核心是实现
Composer\Repository\Vcs\VcsDriverInterface,覆盖getOrigReference()、getBranches()等方法 - 协议识别靠 URL 前缀匹配,例如检测
gitlab-ssh://就触发你的驱动,而不是改写composer.json里的type - 不要试图 patch
Composer\Package\Loader\RootPackageLoader—— 它不负责协议分发
repositories 配置中能写的协议有哪些
在 composer.json 的 repositories 数组里,URL 字段支持的协议取决于仓库 type:
-
"type": "composer"→ URL 必须是可访问的/packages.json端点,协议不限(https://、http://、file://都行) -
"type": "vcs"→ URL 必须是 VCS 原生地址:git@...、https://github.com/...、svn://...;git+ssh://可以,但myproto://...会报Could not determine VCS type -
"type": "artifact"→ URL 必须指向 ZIP/TAR 文件路径,支持file://、https://;不支持ftp://(Composer 默认禁用)
{
"repositories": [
{
"type": "composer",
"url": "https://packagist.example.com"
},
{
"type": "vcs",
"url": "https://gitlab.example.com/group/pkg.git"
},
{
"type": "artifact",
"url": "file:///var/artifacts/"
}
]
}
最容易被忽略的兼容性坑
很多教程教你“改 vendor/composer/...”,这是彻底错误的。Composer 插件必须通过 composer require 安装,并在 composer.json 中声明 "type": "composer-plugin" 和 "extra": {"class": "..."}。否则:
- 升级 Composer 后插件立即失效(vendor 被重写)
- CI 环境因未安装插件导致
composer install失败 - 自定义 VcsDriver 的
getPackages()返回空数组?检查是否忘了调用parent::getPackages()或没正确解析composer.json元数据 - HTTP 仓库返回 401 却没走认证流程?确认插件是否注册了
RemoteFilesystem事件监听器,而非只改了 URL 解析










