composer离线安装失败的根本原因在于默认只信任远程元数据,不读本地缓存;必须通过--prefer-dist预下载、显式配置缓存路径、禁用网络或使用artifact/satis等方案确保元数据与包文件均本地可控。

离线镜像缓存不是“把 vendor 复制过去就行”,而是让 Composer 在无网络时仍能完成 composer install 的完整流程——包括元数据解析、版本比对、包下载与解压。关键不在“有没有包”,而在“它信不信这些包是合法的”。
为什么 composer install 离线后还报 “Could not fetch”
这不是网络超时,是 Composer 根本没尝试读本地缓存。默认行为下,它只信任远程源返回的元数据,composer.lock 里写的 dist URL(比如 https://api.github.com/...)在离线时无法访问,就会直接失败,连 ~/.composer/cache/files/ 里的 zip 都不看一眼。
- 必须提前在联网机执行
composer install --prefer-dist,确保所有包以 dist 形式(zip/tar)下载并落盘到缓存 - 缓存路径要确认:Linux/macOS 是
~/.composer/cache/files/,Windows 是C:\Users\用户名\AppData\Roaming\Composer\Cache\files\ - 离线机上不能只复制缓存目录,还得用
composer config --global cache-files-dir /path/to/cached/files显式指向它,否则 Composer 会忽略 -
COMPOSER_DISABLE_NETWORK=1环境变量可强制跳过所有网络请求,但仅限于已有缓存且composer.lock完整的场景
用 artifact 类型仓库直接读本地 ZIP 包
比依赖全局缓存更可控:你提供包,Composer 只负责解压和装 autoload,不查任何远程地址。适合已知全部依赖版本、且能提前打包的场景。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 把所有
vendor/name-version.zip放进一个目录,比如./packages/archives/ - 在项目
composer.json中加配置:"repositories": [ { "type": "artifact", "url": "./packages/archives" } ] - 注意 ZIP 文件名必须严格匹配
vendor/name-version.zip格式(如monolog/monolog-2.13.0.zip),否则 Composer 找不到 -
artifact不支持分支或 dev 版本,只能用稳定版 tag;如果 lock 文件里锁的是dev-main,得先改composer.lock或用satis生成对应 dist 包
用 satis 构建可 HTTP 访问的静态镜像
这是真正“离线可用”的方案:生成完整的 packages.json + ZIP 包集合,再用本地 HTTP 服务托管。Composer 会把它当普通 Packagist 源一样用,只是地址是 http://127.0.0.1:8000。
- 联网机上运行
php bin/satis build satis.json ./mirror,其中satis.json必须显式列出所有顶层依赖(含require-dev),"require-all": true不推荐——它会试图拉整个 Packagist 子集 - 生成的
./mirror/目录里必须有packages.json和include/all$xxx.json,缺一个,composer update就会报file could not be downloaded - 离线机启动服务:
cd mirror && python3 -m http.server 8000,然后项目中配置:"repositories": [ { "type": "composer", "url": "http://127.0.0.1:8000" } ], "packagist.org": false -
composer clear-cache必须执行,否则 Composer 可能仍 fallback 到旧的远程元数据缓存
离线时 composer update 为什么基本不可行
因为 update 的核心动作是重新 resolve 整个依赖树——它需要实时获取每个包的最新版本列表、约束兼容性、冲突检测。这些元数据全靠远程源提供,本地 ZIP 包或缓存文件不包含版本清单。
- 离线环境下,
composer update即使加了--no-dev--prefer-dist也大概率失败,错误常是Could not parse version constraint或 DNS 查询失败 - 唯一安全的离线操作是
composer install,前提是composer.lock存在、未被修改、且所有包已在本地可访问(缓存 / artifact / satis 镜像三者之一) - 若真需新增包,不要
update,改用composer require vendor/name:1.2.3+artifact或path仓库配合
最易被忽略的一点:离线镜像是否覆盖了所有递归依赖。Satis 不会自动展开 monolog/monolog 依赖的 psr/log,除非你在 satis.json 的 require 里显式写上它——或者先在线跑一次 composer install,再用 composer depends --tree monolog/monolog 把整棵树导出来补全。










