根本原因是PHP未正确配置CA证书路径,需优先设置php.ini中curl.cainfo为绝对路径的最新cacert.pem并重启进程;composer config -g cafile仅影响Composer自身HTTP客户端,不控制底层cURL或OpenSSL验证。

Composer 报 “SSL certificate problem: unable to get local issuer certificate” 或 “CA bundle not found”,根本不是证书本身失效,而是它压根没找到可用的 CA 证书文件路径——配置缺失或指向了不存在的位置。
composer config -g cafile 指定路径为什么无效
常见现象是执行了 composer config -g cafile /etc/ssl/certs/ca-certificates.crt,但 composer diagnose 仍显示 CA file: none 或报错未生效。
- 路径不是绝对路径:
cafile值必须是完整绝对路径,相对路径(如./cacert.pem)会被忽略 - 文件不存在或权限不足:用
ls -l /etc/ssl/certs/ca-certificates.crt(Linux/macOS)或dir C:phpcacert.pem(Windows)确认文件真实存在且可读 - JSON 转义问题(Windows 尤其多见):单反斜杠
C:phpcacert.pem在 JSON 中会被解析为控制字符,必须写成C:/php/cacert.pem或C:\php\cacert.pem - 配置写入了错误位置:加
-g应写入~/.composer/config.json,若该目录被权限锁定(如 root 写入、当前用户无权读),配置实际未加载
php.ini 中 curl.cainfo 和 openssl.cafile 哪个更关键
优先设 curl.cainfo,它比 openssl.cafile 更直接决定 Composer 的 HTTPS 行为。
- Composer 底层用 cURL 发起请求,
curl.cainfo是 cURL 自己读的证书路径,优先级最高 -
openssl.cafile是 OpenSSL 库级配置,仅当 cURL 未显式设置时才可能 fallback 使用 - 检查是否生效:运行
php -r "echo ini_get('curl.cainfo');",输出应为有效路径;若为空或false,说明 php.ini 没生效或路径写错 - 别碰
curl.cainfo以外的 cURL 相关 ini 项(如curl_setopt全局禁用验证),那会破坏所有 PHP cURL 请求
如何快速验证证书路径是否真正起作用
不要一上来就跑 composer update,先做最小闭环验证。
- 查 PHP 当前信任路径:
php -r "print_r(openssl_get_cert_locations());",重点看cafile字段是否为你设的路径,且文件可读 - 绕过 Composer,直测 PHP cURL:
php -r "$ch = curl_init('https://repo.packagist.org/packages.json'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); echo curl_exec($ch);",失败则说明是 PHP 层证书问题,非 Composer 配置问题 - 用
composer diagnose看输出里CA file行是否显示你设的路径,并标为OK;若显示not set或路径后带failed,说明配置未命中 - Linux/macOS 下注意 SELinux 或 AppArmor 限制:即使路径对、文件存在,安全模块也可能阻止 PHP 进程读取证书文件
最易被忽略的是:composer config -g cafile 和 php.ini 中的 curl.cainfo 必须指向同一个真实有效的 PEM 文件。两者冲突时,cURL 扩展以 curl.cainfo 为准,而 Composer 的 cafile 配置只在它自己发起的请求中生效——如果 PHP 环境本身不信任该证书,某些底层操作仍可能失败。











