离线环境下 composer install 报“package not found”是因为默认需联网获取元数据,vendor.zip 无法替代 composer.lock 和 artifact 仓库;正确做法是用 artifact 模式:有网机执行 composer archive 打包依赖到 artifacts/ 目录,离线机配置 artifact 仓库并确保 composer.lock、php 环境及缓存一致。

composer install 为什么报错“package not found”却有 vendor.zip?
离线环境里直接跑 composer install 大概率失败,不是因为命令错了,而是它默认要连 packagist.org 查包元数据、校验 hash、下载源码——没网当然卡在 Package not found 或 Could not parse version constraint。你手里的 vendor.zip 只是结果,不是输入;Composer 不认 zip,只认 composer.lock + 可访问的包源。
怎么让 composer 离线装包:必须用 artifact 模式
核心是把远程包提前下好、存成归档(tar/zip),再告诉 Composer:“别上网了,就从这个本地目录里解包”。这靠 artifact 类型仓库实现,不是改 repositories 为 package 或硬塞 path——后者只适合单个包,且不兼容自动依赖解析。
- 提前在有网机器运行:
composer archive --format=zip --dir=./artifacts/ "monolog/monolog" "^2.0"(会生成./artifacts/monolog-monolog-2.x.x.zip) - 把整个
artifacts/目录拷到离线机,路径记牢,比如/mnt/offline-artifacts - 项目
composer.json里加仓库配置:{"type": "artifact", "url": "/mnt/offline-artifacts/"} - 确保
composer.lock已存在(来自有网环境),且其中所有包版本都已被archive命令打过包
vendor.zip 解压后为什么 vendor/autoload.php 还不工作?
直接解压 vendor.zip 到项目根目录,看似省事,但大概率出问题:autoload 信息没写入 vendor/composer/autoload_*.php,PSR-4 映射丢失,require vendor/autoload.php 会报 Class not found。Composer 的 autoload 文件不是静态的,是根据 composer.json 和实际目录结构动态生成的。
- 解压后必须手动触发生成 autoload:
composer dump-autoload --optimize - 如果提示 “Command 'dump-autoload' is not defined”,说明
composer.phar没放对位置,或用了阉割版二进制(如某些 Docker 镜像自带精简版) - 更稳妥的做法:在有网环境先执行
composer install --no-dev,再打包整个vendor/目录,包含已生成的autoload_*.php
离线导入时容易忽略的三个硬性前提
artifact 模式看着简单,但漏掉任一条件就会静默失败或装错版本:
-
composer.lock必须和 artifact 包严格对应——比如 lock 里写"version": "2.10.2",那artifacts/下就得有monolog-monolog-2.10.2.zip,文件名不能少字母、不能多下划线 - PHP 版本、扩展(如 openssl、zlib)必须和打包时一致,否则 zip 解压失败或 autoloader 加载失败,错误常表现为
failed to open stream: No such file or directory - 离线机不能有残留的
~/.composer/cache/,里面可能存着旧的元数据缓存,导致 Composer 误判包可用性;建议清空或用--no-cache参数运行
最麻烦的其实是版本对齐——一个包依赖另一个包的特定 patch 版本,而你只打了主版本 zip,这时候 artifact 目录里缺文件,Composer 就会退回去尝试联网,然后卡死。得盯着 composer install -v 的输出,看它到底在找哪个 zip 名字。










