离线替换 vendor 前必须确保 composer.lock 未被修改,因其决定 install 行为;需校验锁文件一致性、跳过脚本插件、保留 autoload 文件及权限,并确认所有依赖均为 dist 类型。

离线替换 vendor 前必须确认 composer.lock 未被修改
离线环境下,composer install 的行为完全依赖 composer.lock 中记录的精确哈希、版本和源地址。如果这个文件在离线前被意外改动(比如本地执行过 composer update、手动编辑、或 Git 合并冲突残留),离线替换的包很可能与锁文件不匹配,导致 autoload 失败或类找不到。
实操建议:
- 离线操作前,在联网机器上运行
git status确认composer.lock干净,且与目标环境一致 - 用
composer show --locked导出当前锁定的包列表,保存为locked-packages.txt,供离线核对 - 不要在离线机上运行任何
composer update或composer require,哪怕只是试一下
用 composer install --no-scripts --no-plugins 避免离线触发网络回调
某些包的 post-install-cmd 或插件(如 hirak/prestissimo)会在安装时尝试连接 Packagist 或 GitHub,即使 vendor 已存在也会报错。跳过脚本和插件能绕过这些隐式网络请求。
实操建议:
- 离线替换 vendor 后,进项目根目录,执行:
composer install --no-scripts --no-plugins --no-interaction
- 若提示
Package operations: X installs, Y updates, Z removals,说明 lock 文件和 vendor 不一致——此时不能强装,应重新核对 vendor 来源 - 成功输出
Installing dependencies from lock file+Nothing to install, update or remove才算真正对齐
vendor 替换本身只需文件拷贝,但要注意 vendor/autoload.php 和权限
Composer 不校验 vendor 目录是否“合法生成”,只依赖 autoload 机制和类路径映射。只要结构完整、自动加载器可运行,就认为安装成功。
常见错误现象:
- 替换后报
Class not found:通常是vendor/autoload.php被覆盖或损坏,或其引用的vendor/composer/autoload_*.php缺失 - 报
Permission denied:Linux/macOS 下,从其他机器 tar 解压的 vendor 可能带不可执行位,尤其影响bin/下脚本 - Windows 下路径换行符或大小写问题导致 PSR-4 映射失败(罕见但存在)
实操建议:
- 用
tar -cf vendor.tar vendor/打包(保留权限和符号链接),离线机用tar -xf vendor.tar解压到项目根目录 - 替换后立刻运行
php -r "require 'vendor/autoload.php'; echo 'ok';"验证 autoload 是否可加载 - 检查
vendor/composer/autoload_classmap.php是否存在且非空;若为空,说明 dump-autoload 没跑,需联网机器提前执行composer dump-autoload --optimize并打包
离线环境无法处理 dist 和 source 混用、私有仓库或 path 类型依赖
如果你的 composer.json 里写了 "type": "package"、"repositories" 指向内网 Git、或 "foo/bar": "dev-master" 这种 source 依赖,离线时 composer install 会直接卡住或报 Could not fetch 错误——它根本不会尝试用已有的 vendor。
实操建议:
- 所有私有包必须提前用
composer install在联网机器完成,并确保其代码已完整落入 vendor;不能只拷vendor/foo/bar子目录而不拷vendor/composer/下的映射文件 - 避免在生产部署中使用
path类型依赖;若必须用,需把 path 指向的目录也一并打包进 vendor(并改写composer.lock中对应项的dist.type为path,但极不推荐) - 检查
composer.lock中每个包的dist.type字段:应全为zip或tar,而非git或hg
vendor/composer/autoload_*.php 这些生成文件——它们不是源码,但没它们,整个 autoload 就瘫了。










