答案是先验证包是否存在:访问https://packagist.org/packages/vendor/name确认页面可打开,再用composer search vendor/name和检查包名大小写、不可见字符;若存在则排查镜像失效、同步延迟、缓存残留或repositories配置错误。

不是网络问题,也不是镜像挂了——90% 的 composer require 404 报错,是因为 Composer 根本没去你认为它该去的地方找包。
包名拼写和大小写必须逐字匹配
Composer 对 vendor/name 是严格字符串比对,不忽略空格、不自动转小写、不模糊容错。写错一个字母、多一个下划线、大小写颠倒(比如 spatie/laravel-backup 写成 spatie/Laravel-Backup),就直接报 404,不会提示“相似包”。
- 用
composer search验证:运行composer search spatie backup,看返回结果里是否含完整、准确的spatie/laravel-backup - 手动访问
https://packagist.org/packages/spatie/laravel-backup,确认页面可打开且未标为 abandoned - 复制包名时别从网页或聊天记录粘贴——容易带全角空格、零宽字符;建议手动重打一遍
- 私有包的
name字段必须和composer.json中声明的完全一致,包括 vendor 名、分隔符、连字符
repositories 配置被静默忽略的典型原因
私有包或 Git 仓库报 404,往往不是源不可达,而是 Composer 压根没读你的 repositories 配置——错一个字段,整条就被跳过。
-
type必须是"vcs"(不是"git"、"github",也不能省略) -
url必须是合法git clone地址:https://gitlab.example.com/org/pkg.git或git@gitlab.company:group/repo.git;结尾带#main、/-/tree/main或网页路径会失败 -
{"packagist.org": false}必须作为独立对象,放在repositories数组**末尾**;嵌套、写成"packagist": false或放错位置,都会导致 Composer 继续查官方源兜底 - 配置在项目级
composer.json中时,它优先级低于全局配置;若全局已设镜像,项目级repositories可能被覆盖而失效
镜像源不同步或缓存未刷新的真实表现
包在 Packagist 上明明存在,composer require 却报 404,大概率是镜像还没同步,或本地缓存还在读旧的元数据快照。
- 打开浏览器访问
https://mirrors.aliyun.com/composer/p/spatie/laravel-backup.json(把包名替换成你要的),如果返回 404 或内容里没有目标版本,就是镜像延迟 -
composer clear-cache不会强制重新下载packages.json——Composer 默认复用 15 分钟内未过期的缓存元数据 - 真正有效的是删掉对应镜像子路径:
rm -rf ~/.composer/cache/repo/https---mirrors-aliyun-com-composer - 临时切回官方源验证:
composer config --global repo.packagist composer https://packagist.org,再跑composer require spatie/laravel-backup -vvv;成功则问题出在镜像
为什么 composer search 能搜到,require 却 404?
因为 composer search 只查 Packagist 全局索引,不校验稳定性、PHP 版本、扩展、minimum-stability 设置,也不走你配的 repositories;而 require 是真安装,所有约束都生效。
- 包只有
dev-main分支,但项目设了"minimum-stability": "stable"→ 直接跳过,报 “not found” -
composer search myorg/utils成功,可能只是 Packagist 上有个同名空包;你的私有源根本没被访问 - 运行
composer config repositories,如果输出里还包含https://repo.packagist.org,说明packagist.org没禁用,私有源再靠前也白搭 - 加
-w(--with-dependencies)可能触发依赖冲突误报:Composer 强制解析整个依赖树,某一个老包锁死子依赖,新包就会被判定“无法满足”,错误却显示为 “not found”
最常被忽略的一点:Composer 查包是「从上到下,命中即停」,但这个逻辑只在 packagist.org 被显式关闭后才启用。否则它永远先查官方源兜底——哪怕你 repositories 里第一个就写了私有 Git 地址,也无效。











