项目级 repositories 配置完全覆盖全局配置,且不合并继承;必须显式禁用 packagist.org 并按顺序排列镜像,同时清理 vendor 和 composer.lock 才能使镜像生效。

项目级 repositories 配置永远覆盖全局配置
只要项目根目录的 composer.json 里定义了 repositories 字段(哪怕只是空数组 "repositories": []),全局配置(~/.composer/config.json)里的 repos.packagist 或其他仓库设置就完全失效。Composer 不合并、不继承,只认当前项目的数组。
常见错误是:全局用 composer config -g repos.packagist composer https://mirrors.aliyun.com/composer/ 配好了,但项目里一写 "repositories": [...],镜像立刻失效。
- 验证方式:运行
composer config repositories,输出只显示项目级内容 - 全局配置仅对「未声明
repositories」的项目起作用 - 想临时切镜像又不改项目文件?删掉项目
composer.json里的repositories段再试
packagist.org 默认隐式启用,必须显式禁用才让镜像真正生效
即使你在 repositories 数组第一位写了阿里云镜像 URL,只要没加 {"packagist.org": false},Composer 仍会把官方源当作兜底项——它不在数组里,但在逻辑上永远排在最后。一旦镜像返回 404(比如新包还没同步),Composer 立刻回退到官方源,看起来像“镜像没生效”。
{"packagist.org": false} 必须作为独立对象写入 repositories 数组,且放在末尾(不是开头),键名必须精确为 packagist.org(不能少点、不能多 s、不能写成 packagist)。
- 错误写法:
"packagist": false、{"packagist.org": true}、嵌套在其他对象里 - 正确写法:
{"packagist.org": false}是数组中一个单独元素,和其他镜像或私有源并列 - 验证:执行
composer config repositories,输出中应无https://repo.packagist.org,且明确含"packagist.org": false
repositories 数组顺序 = 查找顺序 = 实际生效顺序
Composer 对 repositories 数组是正向线性遍历:从索引 0 开始,对每个仓库发起元数据请求(如 /packages.json),**首个返回 HTTP 200 + 可解析 JSON 的源即被锁定,后续全跳过**。这不是“优先级”,而是“命中即停”。
它不区分超时、500 还是 DNS 失败——这些错误直接报错退出,根本不会尝试下一个;只有 404 才继续查下一项。
- 想让阿里云镜像真正当主力?把它放在数组第一位
- 腾讯云镜像放第二位没意义,除非你确认它比阿里云更常返回
404(比如同步延迟更久) - 千万别把
https://repo.packagist.org和镜像 URL 同时塞进数组——前者会抢在镜像前发请求,失败即中断 - 私有源要生效,必须放在数组最前面,且其
packages.json必须真实包含目标包的元数据(不能只返回空{"packages":{}})
vendor 和 composer.lock 不清理,换镜像等于白配
composer.lock 文件里记录的是每个包来源的哈希值(包括源地址)。哪怕你已正确配置镜像并运行 composer update,只要 lock 文件里还存着旧的官方源哈希,Composer 就会继续从原站拉取——镜像只影响新安装或更新时的元数据获取和 dist 包下载路径。
同理,vendor/ 目录里已安装的包不会因换镜像而自动重装。
- 实操必须步骤:删掉
vendor/和composer.lock,再跑composer install - CI/CD 中尤其要注意,缓存
vendor/或composer.lock会导致镜像配置被绕过 - 如果用
composer create-project初始化,它生成的lock文件默认绑定官方源,必须清掉重装
repositories 数组 → 严格顺序 → packagist.org 显式禁用 → vendor 和 lock 彻底清理。漏掉其中任意一环,镜像就只是配置文件里的一行文字。











