Composer镜像配置失效的根本原因是键名必须为单数repo.packagist、type值必须显式写composer、URL必须以/结尾,三者缺一即静默fallback至官方源且不报错。

Composer 镜像配置根本不是“换 URL”那么简单,它由 config.json 解析、repositories 合并逻辑、包元数据加载三阶段共同决定;写错 repo.packagist 键名或漏掉 composer type 值,源码层会直接 fallback 到官方地址,且不报错。
为什么 composer config -g repo.packagist 写对了却没生效
Composer 源码里对全局镜像的读取路径非常严格:它只认 repositories.packagist(旧版)或 repo.packagist(2.2+ 主推)这两个键,其他任何拼写(如 repos.packagist、packagist.org、mirror)都会被跳过,静默 fallback 到 https://packagist.org。
-
repo.packagist是单数,不是复数——源码中硬编码校验 key 名,多一个s就进不了镜像分支逻辑 - 中间的
composer是type字段值,不是注释;省略后,RepositoryManager::addRepository()会按默认类型构造PackagistRepository,URL 也被忽略 - URL 末尾缺
/会导致PackageRepository::getPackagesUrl()拼出/composerpackages.json而非/packages.json,404 后直接终止,不提示 - 验证必须用
composer config -g repo.packagist,不能靠composer show -p——后者只显示最终合并后的 repositories 列表,已受项目级配置覆盖
repositories 数组在源码里怎么参与依赖解析
Composer 并不把 repositories 当作“备用下载地址”,而是在 RepositorySet::loadRepositories() 阶段做两件事:先顺序请求每个源的 packages.json(元数据),再合并成一张全局包索引表;安装时只从第一个返回了该包完整版本信息的源拉 ZIP。
- 502、超时、DNS 失败 → 直接中断,不会查下一个源
- 只有明确返回 404(包不存在)→ 才继续查下一个源的
packages.json - 如果项目
composer.json里有"repositories": [](哪怕空数组),RepositoryManager::configureRepositories()会禁用默认 packagist 源,全局repo.packagist完全不加载 - 想保留私有源又加镜像?必须显式写
{"packagist.org": false}在repositories数组开头,否则 Composer 仍会偷偷连官方源
换源后 composer install 报 hash 不匹配的根本原因
这不是网络或配置问题,而是 composer.lock 文件里记录的 dist URL 和 hash 来自旧源(如 https://api.github.com/... 或 https://packagist.org/files/...),切换镜像后,Composer 仍按原 URL 去新镜像站找 ZIP,但镜像站内部路径映射与官方不一致,导致 hash 校验失败。
- 必须删掉
vendor/和composer.lock,再跑composer install(不是update) -
composer update只更新 lock 文件里的版本号,不重写 dist URL 和 hash;只有install会重新走完整解析 + 下载 + 校验流程 - CI 环境下尤其要注意:如果缓存了旧
composer.lock,即使镜像已切,也会持续失败
composer config -g 的配置到底写到哪了
全局配置实际写入 COMPOSER_HOME 目录下的 config.json,Linux/macOS 是 ~/.composer/config.json,Windows 是 %APPDATA%\Composer\config.json。但源码里读取逻辑优先级是:COMPOSER_HOME 环境变量 > COMPOSER 环境变量 > 默认路径。
- Git Bash 和 Windows CMD 的
%APPDATA%路径可能不同,改完没生效,先检查echo $COMPOSER_HOME是否指向预期位置 - CI 流水线常用
www-data或runner用户执行命令,sudo composer config -g写的是 root 配置,但构建进程读不到 - 宝塔面板里 PHP 进程常以
www用户运行,全局配置得用sudo -u www composer config -g ...才能命中 - 验证是否真写进去了,别看终端输出,直接
cat ~/.composer/config.json | grep repo.packagist


















