答案是PHP底层OpenSSL/cURL找不到或读不懂证书文件,需运行php -r "print_r(openssl_get_cert_locations());"确认default_cert_file和ini_cafile路径有效性,再将PEM格式根证书追加至系统CA bundle或为Composer单独配置cafile。

确认 PHP 实际加载的证书路径
报错“证书不完备”不是 Composer 自己缺证书,而是 PHP 的 OpenSSL/cURL 找不到或读不懂证书文件。先查它到底在用哪个路径:php -r "print_r(openssl_get_cert_locations());"。重点关注 default_cert_file 和 ini_cafile 的值——如果为空、指向不存在的文件、或文件权限为 777(PHP 会拒绝加载),就直接导致验证失败。
把自签名根证书追加到系统 CA bundle
这是最稳妥的做法,影响所有 PHP HTTPS 请求(包括 file_get_contents、curl_exec),不只是 Composer。
- 确保你手上有 PEM 格式根证书(以
-----BEGIN CERTIFICATE-----开头,不是 .pfx/.der) - Linux(Debian/Ubuntu):
sudo cp your-root.crt /usr/local/share/ca-certificates/→sudo update-ca-certificates - macOS:双击 .crt → “钥匙串访问” → 选“系统”钥匙串 → 右键证书 → “显示简介” → “信任” → 设为“始终信任”
- Windows:双击 .crt → “安装证书” → “本地计算机” → 存储位置选“受信任的根证书颁发机构”
为 Composer 单独指定 cafile(容器/CI 场景)
当你无法修改系统证书库(比如 Alpine 镜像、GitLab Runner),就让 Composer 显式用你提供的证书文件。
- 把 PEM 格式证书(含完整链:叶证书 → 中间 → 根 CA)放到固定路径,例如
/certs/company-root.crt - 运行:
composer config -g cafile /certs/company-root.crt - 注意:
cafile只对composer命令生效;若用vendor/bin/composer,它默认忽略全局配置,得在命令前加COMPOSER_HOME或改用php -d openssl.cafile=... vendor/bin/composer
别踩这些坑
很多问题其实卡在细节上:
-
curl.cainfo和openssl.cafile在php.ini里必须都设,且指向同一个有效 PEM 文件;只设一个常无效 - 路径含空格或中文?必须用双引号包裹,比如
curl.cainfo = "C:\my certs\cacert.pem" - Homebrew PHP 默认不设
curl.cainfo,但系统已有证书;优先复用/opt/homebrew/etc/ca-certificates/cert.pem而不是硬塞一个下载的 cacert.pem - 改完
php.ini必须重启 CLI 环境(关掉终端重开),否则composer还是读旧配置
证书链顺序、文件权限、CLI 与 Web php.ini 分离——这三个点最容易被跳过,但恰恰决定是否真能跑通。











