私有 packagist 仓库不必强选 satis 或 private packagist;satis 最轻量可控,适合中小团队,仅需两步即可搭建最小可用仓库:编写 satis.json 声明 git 仓库并执行 build 生成静态 packages.json,用 nginx 托管 web/ 目录即可。

私有 Packagist 仓库必须用 Satis 或 Private Packagist?
不是必须。Satis 是最轻量、可控性最强的选择,适合中小团队自建;Private Packagist 功能完整但需付费且部署复杂,多数内部微服务场景用不到它的审计和托管能力。直接用 Composer 的 repositories + Git 链接也能临时跑通,但无法解决版本发现、依赖解析和缓存问题——尤其当多个服务同时 require 同一个内部包的 dev-main 时,Composer 会反复 clone、校验失败,报错类似 Could not parse version constraint dev-main: Invalid version string "dev-main"。
推荐路径:用 Satis 搭建最小可用私有仓库,核心只需两步:
- 写
satis.json,声明哪些 Git 仓库纳入索引(支持 GitHub、GitLab、自建 Gitea) - 执行
php bin/satis build satis.json web/,生成静态packages.json
生成的 web/ 目录可直接用 Nginx 托管,无需 PHP 运行时。注意:Satis 不代理下载,所有 dist 包仍从原始 Git 地址拉取,所以确保各微服务 CI 能访问那些 Git 仓库(比如内网 Gitea 地址)。
共有代码该打包成 library 还是 monorepo 子包?
优先选独立 library,每个共有模块单独一个 Git 仓库(如 company/auth-contract、company/http-client),不要塞进大 monorepo。原因很实际:微服务语言和技术栈可能不同(PHP 服务调 Java SDK),强行共仓会导致发布节奏绑架——A 服务只改了个 DTO,却要触发整个 monorepo 的构建和版本号升级,其他服务还得被动更新。
library 方式下,关键实操点:
- 每个库必须含
composer.json,name字段格式统一为vendor/name(如acme/logging),否则 Satis 无法识别 - 版本打 tag,别依赖
dev-master;Satis 默认只索引带 tag 的 commit,未打 tag 的分支不会出现在packages.json中 - 若需快速验证,本地开发时可用
path类型 repository 临时替代:{"type": "path", "url": "../acme-logging"},但上线前必须切回私有仓库地址
如何让各微服务自动拉取最新稳定版而非 dev-main?
靠 minimum-stability 和 prefer-stable 双重约束。仅设 "minimum-stability": "stable" 不够——如果某个包只有 v1.0.0-beta tag,Composer 会跳过它,导致安装失败;而设 "prefer-stable": true 则在有 stable 版本时自动忽略 beta/rc 版本,哪怕你写了 "^1.0" 也会命中 v1.0.0 而非 v1.0.0-rc1。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
各服务的 composer.json 应显式配置:
{
"minimum-stability": "stable",
"prefer-stable": true,
"repositories": [
{"type": "composer", "url": "https://satis.internal.acme.com/"}
]
}
注意:这个配置不能放在 Satis 的 satis.json 里,必须落在每个微服务自己的 composer.json 中。Satis 只负责提供元数据,不干预客户端解析逻辑。
为什么 vendor/autoload.php 加载不了内部类?
大概率是 PSR-4 映射没对齐。Composer 不会自动扫描私有包的源码结构,必须在每个内部库的 composer.json 里明确定义 autoload:
{
"autoload": {
"psr-4": {
"Acme\Logging\": "src/"
}
}
}
常见错误:
- 路径写成
"src/Logging/",导致命名空间AcmeLogging实际对应src/Logging/src/,最终类找不到 - 用了
classmap但没运行composer dump-autoload,Satis 构建时不会帮你做这步 - Git 仓库根目录下没有
src/,而是lib/或src/Acme/Logging/,映射必须严格匹配物理路径
验证方式:进入某微服务目录,执行 composer show acme/logging,看输出中 autoload 字段是否与你预期一致;再运行 composer install -v,观察 Composer 是否打印 Generating autoload files 及具体映射条目。
真正麻烦的从来不是搭仓库,而是每个内部库的 composer.json 是否干净、可复现、不带本地路径或调试配置——这些细节漏掉一个,就会让十个微服务集体加载失败。










