必须设 CURLOPT_RETURNTRANSFER => true,否则curl_exec()直接输出响应体而非返回字符串;HTTPS请求需配置SSL验证选项或CA证书路径;POST传JSON须设Content-Type头且避免CURLOPT_POST重复设置。

PHP 用 curl_init() 发请求,不是调个函数就完事——没设 CURLOPT_RETURNTRANSFER,结果直接 echo 出来;忘了 curl_close(),长连接下资源会悄悄泄漏;更常见的是 HTTPS 请求卡死,其实只是缺了 CURLOPT_SSL_VERIFYPEER 和 CURLOPT_SSL_VERIFYHOST 的合理组合。
为什么 curl_exec() 没返回内容,反而直接输出到页面?
这是最常踩的坑:默认情况下,cURL 把响应体直接输出(类似 echo),而不是返回字符串。你拿到的返回值可能是 true 或 false,根本不是 JSON 或 HTML。
- 必须显式设置
CURLOPT_RETURNTRANSFER => true,否则curl_exec()不返数据 - 别依赖
curl_setopt($ch, CURLOPT_HEADER, false)来“关掉头信息”——它只控制是否把响应头混进返回值里,不影响主体输出行为 - 如果用了
CURLOPT_HEADER => true,返回值开头会带原始 HTTP 头,需手动explode("\r\n\r\n", $res, 2)分离
HTTPS 请求超时或报 SSL certificate problem: unable to get local issuer certificate 怎么办?
本地开发环境(尤其是 Windows + XAMPP/MAMP)最容易中招。不是证书真有问题,而是 PHP 找不到 CA 根证书路径,或校验太严格。
- 临时调试可加:
CURLOPT_SSL_VERIFYPEER => false和CURLOPT_SSL_VERIFYHOST => false——但仅限开发,上线必须恢复 - 生产环境应指定 CA 包路径:
CURLOPT_CAINFO => '/path/to/cacert.pem'(推荐用 Mozilla 官方cacert.pem) - Windows 下若用系统 OpenSSL,可能还需设
CURLOPT_SSL_CIPHER_LIST => 'TLSv1.2',避免协商失败
curl_setopt_array() 和逐个 curl_setopt() 有啥实际区别?
写法差异小,但影响可读性、调试效率和错误定位。
立即学习“PHP免费学习笔记(深入)”;
- 批量设参数用
curl_setopt_array($ch, [...])更紧凑,适合固定模板请求(如统一加 token、超时、UA) - 动态逻辑(比如根据响应状态重试、按条件开关
CURLOPT_POST)建议单条curl_setopt(),方便加日志或条件断点 - 注意:
curl_setopt_array()遇到非法选项名(如拼错成CURLOPT_RERTURNTRANSFER)会静默失败,不报 warning —— 逐条设更容易发现 typo
POST 请求传 JSON 数据,CURLOPT_POSTFIELDS 怎么设才对?
很多人直接 json_encode($data) 塞进去就跑,但漏了关键两步:Content-Type 声明和编码一致性。
- 必须手动加头:
CURLOPT_HTTPHEADER => ['Content-Type: application/json; charset=utf-8'] -
CURLOPT_POSTFIELDS接收字符串或数组;传 JSON 字符串时,不能同时设CURLOPT_POST => true(它会自动转为application/x-www-form-urlencoded) - 如果后端是 Laravel/Symfony 等框架,还建议加
CURLOPT_USERAGENT => 'PHP-curl',某些中间件会拦截空 UA
真正麻烦的从来不是怎么发起请求,而是当 curl_exec() 返回 false 时,你得立刻知道是 DNS 解析失败、连接被拒、还是 SSL 握手卡在第三步——所以每次初始化后,记得补上 curl_error($ch) 和 curl_getinfo($ch) 的兜底检查。这一步,90% 的线上 curl 超时问题都能当场定位。











