composer卡在loading composer repositories或报curl error 35,主因是php底层tls握手失败,90%以上源于dns解析失败、openssl版本过旧(如1.0.2k不支持tls 1.3)或ca证书路径为空/损坏;composer diagnose仅测http head不验证https,不可信;需用php -r "print_r(openssl_get_cert_locations());"和curl -v双重验证证书路径,并确保php.ini中curl.cainfo与openssl.cafile指向同一有效cacert.pem文件且重启环境。

Composer 卡在 Loading composer repositories 或报 cURL error 35、SSL handshake failed,不是 Composer 本身坏了,而是 PHP 底层 TLS 握手被卡住——DNS 解析失败、OpenSSL 版本太老、CA 证书路径为空或文件损坏,三者占了 90% 以上原因。
为什么 composer diagnose 显示 OK 却 install 卡住
composer diagnose 只对 https://packagist.org 发一次 HTTP HEAD 请求(走 80 端口),不校验 HTTPS、不读你的镜像配置、也不模拟真实依赖解析链路。它通过 ≠ 你实际要用的链路通。
- 你配了阿里云镜像:
composer config -g repos.packagist composer https://mirrors.aliyun.com/composer/,但diagnose仍硬连官方源,完全不生效 - 真正卡点在
Loading composer repositories阶段:本质是 DNS 解析失败,或 TLS 握手卡在 OpenSSL 层,http.timeout参数此时完全无效 - 验证镜像是否真可用,别信
diagnose,改用:composer show -p | head -5或直接curl -I https://mirrors.aliyun.com/composer/packages.json
如何确认是 OpenSSL 证书路径问题而非网络故障
两步闭环验证,比看错误字眼靠谱得多:
- 运行
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 年,文件存在但不含 ISRG Root X1 等现代根证书,openssl 拒绝验证
php.ini 中必须同时配齐 curl.cainfo 和 openssl.cafile
只改一个,PHP 会 fallback 到空信任链;路径不一致,等于没配。两者必须指向同一个 cacert.pem 文件,且为绝对路径。
- Linux/macOS 示例:
curl.cainfo = "/usr/local/etc/php/cacert.pem"和openssl.cafile = "/usr/local/etc/php/cacert.pem" - Windows 示例(推荐正斜杠):
curl.cainfo = "C:/php/extras/ssl/cacert.pem"和openssl.cafile = "C:/php/extras/ssl/cacert.pem"(单反斜杠会被 PHP 当转义符解析) - 证书文件必须从权威源下载:
curl -sS https://curl.se/ca/cacert.pem -o /path/to/cacert.pem,确保权限为 644(Linux/macOS)或 PHP 进程可读(Windows) - 改完必须重启:CLI 模式关掉终端重开;Web 模式(Apache/Nginx/php-fpm)必须重启对应服务——光刷新页面或
service restart不一定 reload 配置
为什么 composer config -g cafile 经常不起作用
这条命令只影响 Composer 自己封装的 HTTP 客户端(基于 php-http),而真实发起 HTTPS 请求的是 PHP 的 cURL 或 OpenSSL 扩展。它无法覆盖 curl.cainfo 的优先级,也不能修复 TLS 握手失败(比如 cURL error 35)。
-
composer config -g cafile /path/to/cacert.pem后可能显示 “CA file configured”,但composer install一旦涉及 Git 克隆、cURL 直连或某些插件调用,还是会走 PHP 原生扩展,cafile配置完全不生效 - 企业环境若使用 Zscaler/Netskope 等 HTTPS 解密代理,
cafile也救不了——得把代理根证书手动加入cacert.pem,或临时设no_proxy="packagist.org,repo.packagist.com" - Docker 构建中建议在
Dockerfile末尾加RUN composer config -g cafile /etc/ssl/certs/ca-certificates.crt,但前提是基础镜像里该路径已存在且含有效证书
最容易被忽略的是:改完 php.ini 后没关终端重开(CLI 模式),或没重启 php-fpm(Web 模式)——配置写得再对,不 reload 就等于没改。还有就是 Windows 下路径用了单反斜杠,PHP 解析失败却静默 fallback,查日志都看不到报错。











