Composer离线安装必须设COMPOSER_DISABLE_NETWORK=1,否则即使vendor和cache存在,仍会请求packages.json导致失败;可靠方式是预生成composer.lock和vendor并打包迁移,且安装后须执行composer dump-autoload -o。

Composer 不能靠缓存实现断网安装 —— 它的缓存机制只服务于联网场景下的下载加速,不提供离线依赖解析或安装能力。你看到的 ~/.composer/cache/files/ 里那些 ZIP 文件,没有元数据绑定,Composer 离线时根本不知道该用哪个、校验谁、是否满足当前 composer.json 的约束。
为什么 composer install 断网就失败,哪怕 vendor 和 cache 都在?
因为默认行为是:即使 vendor/ 已存在、composer.lock 也完整,Composer 仍会尝试请求 https://repo.packagist.org/packages.json 做元数据校验。这个请求无法跳过,除非你显式切断网络通路。
- 错误不是“找不到包”,而是
Could not fetch https://repo.packagist.org/packages.json或Connection refused -
COMPOSER_DISABLE_NETWORK=1是硬性前提,不设它,所有--no-xxx参数都无效 - 即使缓存目录里有对应 ZIP,没
composer.lock提供的dist.url和dist.shasum,Composer 就无法定位和校验它
离线安装唯一可靠路径:预生成 + 禁用网络
真正能离线安装的,只有提前在有网机器上生成好 composer.lock 和完整 vendor/,再打包过去。缓存只是中间产物,不能替代这个流程。
- 在有网机上,先编辑
composer.json,追加你要的包(如"monolog/monolog": "^2.10") - 运行
composer update monolog/monolog --no-dev --prefer-dist --no-scripts --no-plugins - 确认
vendor/和composer.lock都已更新,再打包整个项目目录(含composer.json、composer.lock、vendor/) - 离线机上,设置
COMPOSER_DISABLE_NETWORK=1,再执行composer install --no-interaction --no-plugins --no-scripts --no-dev
为什么不能只拷 ~/.composer/cache/files/ 过去?
缓存 ZIP 是无状态的二进制文件,没有版本号、包名、约束条件等上下文信息。Composer 离线时无法反向推导出“这个 ZIP 对应 acme/utils 的 dev-main 版本且满足 ^1.2”。
- 缓存只在
install阶段参与解压,前提是composer.lock已存在且每个包的dist.shasum能匹配缓存中某个 ZIP - 一旦
composer.lock缺失、被修改、或某包标记为"source": {"type": "git"},缓存就完全失效 - 全局缓存路径在 Windows 是
C:\Users\用户名\AppData\Roaming\Composer\Cache\files,Linux/macOS 是~/.composer/cache/files/,但拷过去也没用
最易被忽略的一点:离线执行 composer install 后,必须立刻补一记 composer dump-autoload -o。否则即使文件都在,Class not found 依然高频出现——因为 autoload 映射没重建,而这个步骤默认被 --no-autoloader 跳过了。











