先运行php -r "print_r(openssl_get_cert_locations());"检查default_cert_file和ini_cafile是否为空、路径不存在或文件≤10KB;再执行curl -v https://packagist.org/packages.json,若同样报SSL证书错误,即可确认是OpenSSL证书路径问题而非网络或代理故障。

怎么确认是 OpenSSL 证书路径问题,不是网络或代理故障
别看报错里有没有“SSL”字眼,直接让 PHP 自己说:运行 php -r "print_r(openssl_get_cert_locations());"。重点盯 default_cert_file 和 ini_cafile 两个字段——如果为空、路径不存在、或对应文件大小 ≤10KB(说明是空包或旧版 bundle),就是它了。
再补一刀:curl -v https://packagist.org/packages.json。如果也报 SSL certificate problem: unable to get local issuer certificate,说明问题出在 PHP/cURL 层,跟 Composer 镜像、代理、DNS 全都无关。
Windows 用户尤其容易误判:XAMPP/WAMP 自带的 curl-ca-bundle.crt 多数停更于 2021 年,文件存在但内容过时,file_get_contents() 能读,openssl 却拒绝验证——得看实际内容是否含现代根证书(比如 ISRG Root X1)。
Windows 下必须同时配对 curl.cainfo 和 openssl.cafile
只改 curl.cainfo 或只改 openssl.cafile 都没用。PHP 在不同场景下会分别读取这两个值,缺一就 fallback 到空信任链。
下载最新证书:curl -sS https://curl.se/ca/cacert.pem -o C:/php/extras/ssl/cacert.pem(路径必须存在,建议先手动建好 C:/php/extras/ssl/ 目录)
编辑 CLI 模式真正生效的 php.ini(先跑 php --ini 确认 Loaded Configuration File 路径),在文件末尾加两行,路径用正斜杠、带双引号、绝对路径:
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
curl.cainfo = "C:/php/extras/ssl/cacert.pem" openssl.cafile = "C:/php/extras/ssl/cacert.pem"
改完必须关掉当前终端、新开一个——CLI 模式不重启终端,新配置不生效。
为什么改了 php.ini 还不生效
常见原因有三个:
- CLI 和 Web 服务(如 Apache/Nginx + php-fpm)加载的是不同的
php.ini,php --ini只显示 CLI 的路径,Web 环境需单独查phpinfo()或服务配置 -
openssl扩展本身未启用:运行php -m | grep openssl,若无输出,需在对应php.ini中取消注释;extension=openssl - 路径用了反斜杠且没转义,或双引号缺失导致解析失败;推荐统一用正斜杠 + 双引号包裹
验证是否生效:php -r "print_r(openssl_get_cert_locations());" 输出的 default_cert_file 应与你写的路径一致,且该文件 dir C:\path\to\cacert.pem 能看到、大小正常(通常 >200KB)。
别信 XAMPP/WAMP 自带的证书文件
它们常默认指向 C:\php\extras\ssl\curl-ca-bundle.crt,但该路径往往根本没创建,或者文件是空的、删了、或内容早已过期。
稳妥做法永远是自己下载、自己存、自己配:
- 从
https://curl.se/ca/cacert.pem下载最新cacert.pem - 保存到一个你可控的路径,例如
C:/php/extras/ssl/cacert.pem - 确保目录存在(
mkdir C:\php\extras\ssl),权限允许 PHP 读取 - 在
php.ini里明确写死这两行,不依赖任何“默认”
最易被忽略的一点:证书文件本身是否真的含现代根证书。打开 cacert.pem,搜索 ISRG Root X1 或 DST Root CA X3(后者已过期,前者是 Let’s Encrypt 当前主力)。没有?说明下载失败或被缓存覆盖了旧文件。

















