composer项目迁移必须重装依赖而非复制vendor目录,因vendor含平台相关二进制、绝对路径硬编码及php版本绑定符号链接,直接拷贝会导致class not found等错误;须保留composer.json和composer.lock,仅执行composer install。

Composer 项目迁移不是复制粘贴 vendor 文件夹,而是重装依赖——否则极大概率在新环境报错或行为异常。
为什么不能直接拷贝 vendor 目录
因为 vendor 里包含平台相关二进制(如 phpunit 的 phar 入口、扩展的 .so/.dll)、绝对路径硬编码(部分包在安装时写入 composer/autoload_classmap.php)、以及与本地 PHP 版本/扩展严格绑定的符号链接。直接迁移后常见现象:Class not found、command not found、failed to open stream。
- 不同机器的 PHP 版本不一致 → 某些包会跳过安装或降级,但
vendor里残留旧版,导致运行时类名冲突 -
composer.lock中记录的是“精确哈希”,但若没提交它,或新机器用了不同 Composer 版本(如 v1 vs v2),install行为可能不一致 - 某些包(如
laravel/sail、symfony/flex)会在安装时执行脚本,生成本地配置,这些不会随vendor复制生效
必须保留的三个文件/目录
迁移前确认以下内容已纳入版本控制并同步到目标环境:
-
composer.json—— 声明依赖和脚本的唯一权威来源 -
composer.lock—— 锁定所有依赖的确切版本和哈希,保证可重现安装;没有它,composer install会退化成update,结果不可控 -
vendor/autoload.php不用管——它由 Composer 自动生成,只要前两者存在,运行composer install就会重建
composer install 和 composer update 怎么选
迁移场景下,只用 composer install;除非你明确想升级依赖或解决兼容性问题,否则绝不用 composer update。
-
composer install:读取composer.lock,逐个下载锁定版本,不修改 lock 文件 → 安全、可预期 -
composer update:忽略lock,按composer.json解析最新满足约束的版本,重写lock→ 迁移中等于主动引入不确定性 - 如果提示
Your lock file does not contain a compatible set of packages,说明composer.json和lock冲突,应先检查是否误改了json,而不是直接update
常见卡点与绕过方式
执行 composer install 卡住或失败,优先看网络和权限,而非怀疑命令本身:
- 国内机器常因 packagist.org 超时失败 → 运行
composer config -g repo.packagist composer https://packagist.phpcomposer.com(注意:该镜像已停用)或改用https://packagist.org+composer config -g repos.packagist.type composer并配合代理 - 提示
Could not fetch https://api.github.com/... 401→ GitHub Token 权限不足,需在~/.composer/auth.json中补全github-oauth配置 - PHP 扩展缺失(如
ext-zip未启用)→composer install会直接报错,先运行php -m | grep zip确认,再启用对应扩展 - 内存不足报
Allowed memory size exhausted→ 临时加大限制:COMPOSER_MEMORY_LIMIT=-1 composer install
真正麻烦的从来不是命令怎么敲,而是 composer.lock 是否干净、PHP 环境是否对齐、以及有没有人悄悄删掉了 auth.json 里的私有仓库凭证。