必须删除 vendor 和 composer.lock 后执行 composer install,因 lock 文件硬编码旧 provider 地址,换镜像后仍会请求失效 url 导致 404。

composer config -g repo.packagist 输出不对就别往下试了
Composer 2.2+ 只认 repo.packagist 这个精确键名,写成 repos.packagist、repositories.packagist.org 或漏掉 -g 都会静默失效,最终 fallback 到 https://packagist.org,不报错也不提醒。
运行后必须看到类似这样的输出:{"type":"composer","url":"https://mirrors.aliyun.com/composer/"}。如果返回 null、空行、https://packagist.org 或报错,说明配置根本没写进去。常见原因包括:
- 命令末尾漏了
composer类型参数,正确写法是composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/ - URL 少了末尾
/,比如https://mirrors.aliyun.com/composer会导致路径拼成/composerpackages.json,直接 404 - 用了 root 用户配,但实际以 www 用户执行(如宝塔、CI 环境),得用
sudo -u www composer config -g单独配
curl -I 测镜像地址比看文档更准
别信“这个镜像应该还活着”,直接测真实响应:
-
curl -I https://mirrors.aliyun.com/composer/packages.json—— 必须返回HTTP/2 200,任何404、301、超时都说明镜像不可用 -
curl -I https://mirrors.tuna.tsinghua.edu.cn/composer/p/monolog/monolog.json—— 看Last-Modified时间是否在最近 30 分钟内,判断同步是否延迟 - 如果返回 HTML 内容(比如“Not Found”页面)或乱码,基本是用了已下线源,如
https://packagist.phpcomposer.com
删 vendor 和 composer.lock 比清缓存更重要
composer clear-cache 只清下载缓存,不碰元数据;而 composer.lock 里硬编码了 provider 地址(比如 https://packagist.org/p2/xxx.json),换镜像后 Composer 仍会优先请求这个旧 URL —— 它早就不通了。
- 必须删掉
vendor/和composer.lock(尤其后者) - 再跑
composer install,不是update——update会复用 lock 里的坏地址 - 如果项目
composer.json里有repositories字段,哪怕只是空数组[],也会屏蔽全局镜像;临时验证可加--no-plugins --no-scripts,或改用composer install -vvv看第一行下载地址
私有包 404 要检查 repositories 顺序和认证
镜像只代理公开包,不代理私有仓库。如果你把阿里云镜像写在 repositories 数组前面,Composer 就会先去镜像查私有包——而镜像根本没有,直接返回 404。
- 必须把私有源写在镜像前面:
"repositories": [{"type": "composer", "url": "https://your-private-repo.com"}, {"type": "composer", "url": "https://mirrors.aliyun.com/composer/"}] - 私有源 URL 必须返回合法的
packages.json,且Content-Type为application/json;用curl -I https://your-private-repo.com/packages.json验证状态码和头信息 - CI 环境下私有源认证常失效:GitHub Actions 默认不读你本地的
~/.composer/auth.json,要用COMPOSER_AUTH注入,域名必须和repositories中的 URL 完全一致(含端口、协议)
最易被忽略的是 composer.lock 里硬编码的 provider 地址 —— 它不会随镜像切换自动更新,不删它,所有修复动作都是白忙。











