必须将私有源置于repositories数组首位并显式禁用默认源{"packagist.org": false},否则Composer会按顺序匹配至packagist.org而静默跳过私有配置,导致Could not find package。

想让某个包走特定源,不是改个 URL 就行——repositories 里类型(type)写错、顺序放反、没关默认源,composer require 就会静默跳过你的配置,最后报 Could not find package。
为什么加了 repositories 还是拉不到私有包
根本原因是 Composer 不会“自动发现”你加的源,它只按 repositories 数组顺序逐个匹配:先看第一个源有没有声明这个 vendor/name,没有就往下找;一旦走到 packagist.org(默认开启),就可能装到公开旧版,甚至覆盖你本意要装的私有版本。
- 必须显式关闭默认源:
{"packagist.org": false}要作为数组中的一项,不能塞进别的仓库对象里 -
type字段漏写或写错(比如把私有 Packagist 服务配成"type": "vcs"),整个仓库会被忽略,不报错也不提示 - 私有 Git 仓库 URL 必须能本地
git clone成功;HTTPS 带 token 的写法(如https://token:x-oauth-basic@...)不能硬编码在composer.json中 - 运行
composer config repositories确认当前生效的源列表,避免被全局config.json覆盖
vcs / composer / path 三种 type 怎么选
它们解决的是完全不同的问题,混用会导致行为不一致甚至失败:
-
"type": "vcs":对应 Git/SVN/Hg 仓库地址,Composer 会 clone 并读取其中的composer.json;适合开发中调试 fork 后的 patch,或未发布到 Packagist 的内部 SDK -
"type": "composer":对应一个提供packages.json的 HTTP 服务(如 Satis、Private Packagist、阿里云镜像);适合团队级私有包统一管理,安装快、可缓存 -
"type": "path":指向本地文件系统路径(如"../my-sdk"),要求该目录下有合法composer.json;仅限本地联调,加"options": {"symlink": true}可软链热更新,切勿用于 CI 或生产
require 时怎么写才能命中自定义源
包名和版本不是“大概对得上就行”,而是严格字符串匹配 + 可解析约束:
- require 的
vendor/name必须和自定义源中实际声明的name字段完全一致(包括大小写、斜杠) - vcs 类型下,
dev-main这类分支名必须真实存在;若仓库默认分支是develop,就得写dev-develop,否则报Could not find a branch or tag matching 'dev-main' - composer 类型源要求其
packages.json文件顶层包含该包的 provider 条目;用curl -s https://your-repo/packages.json | jq '.providers["vendor/name"]'可验证 - path 类型下,本地包的
composer.json必须有name字段,且 require 时版本只能写dev-main、dev-master等开发分支标识,不能写^1.0
认证信息不能写在 composer.json 里
HTTP Basic 或 API Token 写进 composer.json 是高危操作,Composer 强制要求分离存储:
- 项目级凭证放项目根目录的
auth.json,内容形如:{"http-basic": {"private-packagist.example.com": {"username": "api", "password": "pk_abc123..."}}} - 全局凭证放
~/.config/composer/auth.json(Linux/macOS)或%APPDATA%\Composer\auth.json(Windows) - Git over SSH?靠系统 SSH Agent,不走
auth.json;CI 场景可用COMPOSER_AUTH环境变量注入 JSON 凭据 - 配完记得
composer update --no-scripts测试是否真能拉下来,别等上线才发现卡在认证环节
最常被忽略的其实是 repositories 数组的顺序和 {"packagist.org": false} 的位置——它必须是数组中独立一项,不是附属字段;一旦顺序或结构出错,Composer 就当它不存在,连日志都不会输出警告。











