composer本地源本质是用satis构建的静态仓库,需显式声明包版本、生成含packages.json和dist/目录的结构,并通过http服务暴露,项目须配置repo.packagist指向该地址且删除旧lock文件后执行composer install。

本地源不是“镜像”,是离线包仓库
Composer 本身不支持传统意义上的“本地镜像源”——它没有内置的 rsync 同步逻辑,也不会自动把 packagist.org 全量拉下来建个本地服务。所谓“本地源”,本质是用 composer-satis 或 toran-proxy(已停更)这类工具,把指定包打包成静态 JSON + ZIP 的组合,再通过 HTTP 服务暴露出去。你得自己搭一个最小 Web 服务(比如 PHP 内置服务器),让 Composer 把它当普通 Composer 源来用。
用 satis 构建可离线使用的本地源
这是目前最可控、最轻量的方案,适合无网环境或强审计要求场景。关键点不在“怎么装”,而在“怎么生成可用的包列表”:
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 必须显式声明要包含的包和版本:
satis.json里不能只写"require-all": true,否则会尝试抓取 packagist.org 元数据——这在无网时直接失败;得列清楚如"topthink/think": "v6.3.0"、"monolog/monolog": "^2.10" - 生成命令必须带
--no-interaction和--skip-errors:网络不通时,php bin/satis build默认会卡在 DNS 查询或 TLS 握手,加这两个参数才能跳过不可达源 - 生成后目录结构必须含
packages.json和dist/子目录:Composer 只认这个结构,http://localhost:8000/packages.json要能返回合法 JSON,且每个包的dist.url必须指向同域下的 ZIP 路径(如"dist": {"url": "http://localhost:8000/dist/monolog/monolog/2.10.0.zip"}) - 本地服务不能用
php -S直接跑根目录:它默认不支持子路径重写,会导致 ZIP 下载 404;正确做法是进web/目录(satis build 默认输出在此)再启动:php -S localhost:8000 -t ./web
项目中如何安全切换到本地源
别用 --repository 临时参数——它只影响当前命令,但 composer.lock 仍记录远程 URL,下次联网再 install 就会冲突。必须走正式配置流程:
- 项目根目录执行:
composer config repo.packagist composer http://localhost:8000/(注意末尾斜杠,且必须是 HTTP,HTTPS 在无网环境没意义) - 删掉
vendor/和composer.lock:本地源的包 hash 和官方源不同,保留旧 lock 文件会导致校验失败 - 运行
composer install --no-interaction:避免交互式提示中断流程,尤其 CI 或批量部署时 - 验证是否真走本地:加
-vvv看日志,确认所有Downloading行的 URL 都是http://localhost:8000/dist/...,而不是https://api.github.com/...
为什么不用 packagist-mirror 或私有 Packagist 服务
这些方案依赖完整同步 packagist.org 元数据,对无网环境不适用:
-
packagist-mirror需要定期git pull元数据仓库,首次 sync 就要联网下载数 GB 的 JSON 和 ZIP,后续增量更新也依赖网络 - 私有 Packagist(如 Private Packagist)是商业 SaaS,必须连其 API 才能注册 token、推送包、解析依赖,离线等于不可用
- 真正离线场景下,唯一可靠路径是:人工选包 → satis 构建 → 本地 HTTP 服务 → 项目绑定 → 锁定版本。复杂点在于维护
satis.json的版本清单,容易漏包或版本错配,这点没法绕开










