必须运行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 本身不可用,就会直接报错。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 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。

















