repositories必须是索引数组,不能用对象;composer仅识别["repositories": [{}, {}]]格式,键值对写法会导致仅最后一个仓库生效;type必须严格匹配源类型(composer/vcs/package),且私有源须置顶并显式禁用packagist.org。

repositories必须是索引数组,不能用对象键名
Composer只认repositories字段为纯索引数组([{}, {}]),写成带键名的对象(如{"my-mirror": {...}})会导致只加载最后一个元素——前面的全被忽略。这是最隐蔽的配置失效原因。
- 正确写法:
"repositories": [{"type": "composer", "url": "https://mirrors.aliyun.com/composer/"}, {"type": "vcs", "url": "https://gitlab.example.com/my/pkg.git"}] - 错误写法:
"repositories": {"aliyun": {"type": "..."}, "gitlab": {"type": "..."}}→ 只生效gitlab那个 - 验证方式:运行
composer config repositories,输出应为带数字索引的列表,而非键值对
type决定行为,填错就查不到包
type不是随便选的标签,它绑定了底层协议和解析逻辑。配错type,哪怕url完全正确,Composer也不会按你预期工作。
使用ydata-profiling(前身为pandas-profiling)生成全面的数据质量报告,包含相关性分析、缺失值模式和基数检测。导出交互式HTML仪表板和JSON摘要。
-
"type": "composer"→ 期望目标URL返回一个包含packages.json的完整索引服务(如 Satis、Private Packagist、阿里云镜像);Composer会发HTTP请求去查/packages.json -
"type": "vcs"→ 把url当Git/SVN仓库地址处理;Composer会尝试git clone该地址,并读取其根目录下的composer.json;不支持自动发现同域名下其他包 -
"type": "package"→ 手动声明单个包的元数据;适合闭源分发或临时补丁,但无法支持dev-main这类分支别名 - 典型报错:
Could not find package vendor/name,但curl -I https://your-repo/packages.json返回200 → 很可能type误配成了vcs
顺序即优先级,packagist.org必须显式禁用
Composer查包是线性短路:从repositories第一个元素开始匹配,找到同名包就立刻停止,后面所有源(包括默认的packagist.org)全部跳过。这不是fallback,是硬截断。
- 私有包要优先拉取,它的源必须放在
repositories数组最前面 - 想彻底屏蔽官方源,必须在
composer.json顶层加"packagist.org": false(注意:不在repositories数组内,而是同级字段) - 如果没禁用,即使你配了10个私有源,只要lock文件里记录的是旧版本,Composer仍可能回退到
packagist.org拉取——导致版本不一致或认证失败 - CI环境务必禁用并显式加回镜像源,避免依赖开发者本地配置
require时没走私有源?先确认包名是否被源声明
Composer不按域名匹配源,而是严格比对vendor/name是否出现在某个源的索引中。私有源返回200不代表包就“存在”。
- 检查私有源的
packages.json是否真包含"vendor/name"条目(不是嵌套在子路径或providers块里没展开) - 自建静态文件服务时,确保
packages.json是根路径文件,且含完整providers字段(Satis需开启providers生成) - 运行
composer require vendor/name -vvv,看日志里实际请求了哪个URL;如果始终没访问你的私有源地址,说明根本没命中 - 全局
~/.composer/config.json里的repositories会被合并,但项目级composer.json永远优先;别以为配一次全局就万事大吉
composer.json后,composer install不会重新评估源配置——必须跑composer update --lock或删掉composer.lock再重装,否则旧的源记录还在锁文件里。










