Composer架构升级:从v1版本平滑迁移至v2高性能版本
Composer从v1升级到v2必须使用官方提供的升级脚本重新安装,self-update命令已移除。升级后需清除shell缓存,删除vendor目录和composer.lock文件并重新生成。旧插件例如hirak/prestissimo因不兼容会导致静默安装失败,需要移除。持续集成(CI)环境需同步更新缓存及PHP版本。
Composer 升级到 v2 这件事,核心就一句话:必须重装,不能用 composer self-update 升级。这个命令从 Composer 2.5.0 起就被彻底移除了,执行后会直接报错 Command "self-update" is not defined。所以,别在这上面浪费功夫。
怎么确认你还在用 Composer 1.x?
别只信 composer --version 的输出——它可能被缓存或指向了旧文件。更靠谱的做法是:
- 先运行
which composer看路径,比如/usr/local/bin/composer或/opt/homebrew/bin/composer。 - 再运行
ls -l $(which composer),如果输出里有->,说明这是个符号链接。 - 如果是链接,用
readlink -f $(which composer)找到真实文件位置。 - 若路径在
/usr/bin或/usr/lib/php这类系统保护目录,而且你写权限不足,就别硬sudo覆盖了。
容易误判的场景:macOS 上 Homebrew 安装的老版本,which composer 指向 /opt/homebrew/bin/composer,但实际执行的是硬链接到某个已废弃的 composer.phar;Linux 上软链到 /usr/local/bin/composer.phar,版本信息其实是那个文件的内容。别被表象骗了。
为什么必须用官方脚本重装,而不是手动下载替换?
因为 Composer 2 的安装脚本内置了 SHA-384 校验和 GPG 验证,绕过它等于放弃安全校验。唯一推荐的方式是:
- 执行
curl -sS https://getcomposer.org/installer | php -- --filename=composer --install-dir=/usr/local/bin/。 --install-dir必须和which composer输出的路径一致;不确定就先放到$HOME/bin,再确保该目录在$PATH前置(比如export PATH="$HOME/bin:$PATH")。- 别手动下载
composer.phar然后sudo mv替换——这跳过了签名验证。 - 重装完立刻运行
hash -r(bash/zsh)或重启终端,否则 shell 还缓存着旧路径,composer --version仍显示 1.x。
升级后 composer install 卡在 “0 installs, 0 updates” 怎么办?
这不是网络卡死,是插件不兼容导致的静默失败。Composer 2 默认启用 plugin API v2,而老插件(比如已废弃的 hirak/prestissimo)根本不兼容,加载时被跳过,后续逻辑就中断了。可以这样排查:
- 检查项目根目录的
composer.json,删掉"config": { "plugins": ... }里所有已知不兼容插件。 - 运行
composer diagnose,它会告诉你哪些插件被禁用、签名是否启用、是否启用了沙箱等关键状态。 - 如果仍卡住,临时加
-vvv查看详细日志:composer install -vvv,重点关注Loading plugin和Executing command行。
为什么删 vendor 和 composer.lock 是强制步骤?
Composer 2 的依赖解析器完全重写了,composer.lock 的格式也变了。它新增了 content-hash 字段、"lock-version": 2、支持多平台哈希。直接复用旧 composer.lock 会报错:Your lock file does not contain a compatible set of packages。所以,必须删除整个 vendor/ 目录(不要只删子目录)和 composer.lock(保留 composer.json),再运行 composer install 生成全新 lock 文件。若失败,可先试 composer install --ignore-platform-reqs 排查 PHP 版本或扩展问题。
最容易被忽略的一点:CI 环境(比如 GitHub Actions)中,composer.lock 往往被缓存,升级后若未清缓存或未更新 workflow 中的 PHP 版本,会持续失败。那不是脚本的问题,是环境没对齐。


































