必须运行php -r "new ziparchive();"不报错且php -r "echo ziparchive::checksum_crc32;"输出数字,才证明ziparchive类真正可用;同时需确认cli php.ini启用extension=zip、proc_open未被禁用、tmpdir空间充足。

Composer 报 unzip 解压失败,90% 不是缺 unzip 命令,而是 PHP 的 ZipArchive 类根本不可用 —— 别急着装系统工具,先验证扩展是否真就绪。
怎么确认 ZipArchive 真能用(不是只显示在 php -m 里)
很多人运行 php -m | grep zip 看到输出就以为搞定了,结果 composer install 还是崩。这说明扩展只是“注册了”,但类没加载成功或 ABI 不兼容。
- 必须跑:
php -r "new ZipArchive();"—— 不报错才算通过 - 再跑:
php -r "echo ZIPARCHIVE::CHECKSUM_CRC32;"—— 能输出数字(比如1),代表 libzip 库版本够新、ABI 兼容;若报Undefined class constant,说明底层库太老(常见于 CentOS 7 自带的 libzip 0.10) - 检查 CLI 实际读的配置:
php --ini,确认对应php.ini里有extension=zip(Linux/macOS)或extension=php_zip.dll(Windows) - Docker 用户特别注意:
php:8.2-cli-alpine这类镜像默认不带 zip 扩展,得手动加RUN apk add --no-cache zlib-dev && docker-php-ext-install zip
unzip 命令缺失时 Composer 怎么 fallback
错误信息含 Unzip with unzip command failed, falling back to ZipArchive class,说明 Composer 尝试调用系统 unzip 失败,转而依赖 PHP 的 ZipArchive —— 但如果你的 ZipArchive 本身不可用,就会直接报错。
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
- Linux(Ubuntu/Debian):
sudo apt install unzip(仅装命令,不解决 PHP 扩展问题) - Linux(CentOS/RHEL):
sudo yum install unzip或sudo dnf install unzip - macOS(Homebrew):
brew install unzip - Windows:从 7-Zip 官网 下载安装,并确保
7z.exe在PATH中;然后用COMPOSER_UNZIP=7zip composer install强制走 7z 解压(比原生unzip更稳)
proc_open 被禁用导致 ZipArchive 失效
ZipArchive::extractTo() 内部依赖 proc_open() 启动子进程做校验或解压后处理。如果它被禁用,new ZipArchive() 可能不报错,但 extractTo() 一定失败,错误堆栈里常带 proc_open is disabled 或静默回退。
- 查禁用函数:
php -i | grep "disable_functions",看输出里有没有proc_open - 修改对应
php.ini(注意是 CLI 版本!),删掉disable_functions行里的proc_open,保存后重启 CLI 环境(Docker 需重建容器,WSL 可能需重开终端) - 宝塔用户:【软件管理】→【PHP 设置】→【禁用函数】→ 删除
proc_open - 别信“我只用 Web,CLI 不重要”——Composer 只走 CLI PHP,Web 配置改了也没用
临时空间不足引发 extractTo 失败(最隐蔽的坑)
ZipArchive::extractTo(): failed to open stream 看似权限问题,实际大概率是 /tmp 分区满、inodes 耗尽,或 TMPDIR 不可写。Composer 解压时先拷 ZIP 到临时目录,再解,最后挪进 vendor/。
- 查空间和 inodes:
df -h && df -i,重点看/tmp或sys_get_temp_dir()返回的路径 - 改临时路径(立即生效):
export TMPDIR="/path/to/big/disk/tmp" && mkdir -p "$TMPDIR" && chmod 777 "$TMPDIR" - 验证是否生效:
php -r "echo sys_get_temp_dir();"应输出新路径 - 别只改
COMPOSER_CACHE_DIR—— 缓存目录不影响解压阶段,TMPDIR才是关键
真正卡住人的,从来不是“要不要装 unzip”,而是 php -r "new ZipArchive()" 这一行没跑通,或者 proc_open 被悄悄禁用、TMPDIR 指向了一个只剩 3 个 inodes 的分区。环境细节藏在 CLI PHP 的真实配置里,而不是你想象中那个“应该没问题”的 php.ini。










