使用 curl 前须检测函数存在性;ssl 校验选项需用整数 0/2;curl_exec 后必须用 curl_errno 判断错误;php 8.1+ 的 headerfunction 回调需兼容类型声明并返回头长度。

curl_init() 之前先检测函数是否存在
PHP 5.0+ 都内置 cURL,但某些精简版环境(如部分 Docker 镜像、OpenWrt PHP)可能禁用 curl_init。直接调用会报 Fatal error: Uncaught Error: Call to undefined function curl_init()。
必须在初始化前加兜底判断:
if (!function_exists('curl_init')) {
throw new RuntimeException('cURL extension is not loaded');
}
不建议用 @curl_init() 抑制错误——它掩盖了真实缺失问题,且 PHP 8.0+ 已限制部分 @ 操作符效果。
curl_setopt() 的布尔值参数要适配 PHP 7.3+ 变更
PHP 7.3 起,curl_setopt 对 CURLOPT_SSL_VERIFYPEER 和 CURLOPT_SSL_VERIFYHOST 的布尔值处理更严格:传 false 会被转为 0,但部分旧版本 cURL 库要求显式整数 0 才生效,否则仍校验证书。
立即学习“PHP免费学习笔记(深入)”;
跨版本安全写法是统一用整数:
-
CURLOPT_SSL_VERIFYPEER→ 设为0(不是false) -
CURLOPT_SSL_VERIFYHOST→ 设为0或2(1已废弃,PHP 7.3+ 会警告) - 其他布尔选项如
CURLOPT_RETURNTRANSFER、CURLOPT_HEADER仍可用true/false,无兼容问题
curl_exec() 后必须用 curl_errno() 判断失败,不能只看返回值
curl_exec 在出错时可能返回 false,但也可能返回空字符串 ''(比如 HTTP 200 但响应体为空),仅靠 === false 会漏判网络层失败。
正确做法是始终检查错误码:
$ch = curl_init('https://api.example.com');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$errno = curl_errno($ch);
if ($errno !== 0) {
$error = curl_error($ch);
throw new RuntimeException("cURL error {$errno}: {$error}");
}
curl_close($ch);
注意:curl_errno 必须在 curl_exec 之后、curl_close 之前调用,关闭后错误码会被清空。
PHP 8.1+ 的 CURLOPT_HEADERFUNCTION 回调需接受 string 类型参数
PHP 8.1 引入严格类型检查,CURLOPT_HEADERFUNCTION 指定的回调函数若声明参数为 string $header,在旧版 PHP 会报致命错误。反之,若不声明类型,在 PHP 8.1+ 会触发 TypeError。
兼容写法是去掉类型声明,或用联合类型(仅限 PHP 8.0+):
// 安全通用写法(所有 PHP 7.2+ / 8.x)
$headerCallback = function ($ch, $header) {
if (stripos($header, 'Content-Type:') === 0) {
// 处理 header
}
return strlen($header); // 必须返回长度
};
curl_setopt($ch, CURLOPT_HEADERFUNCTION, $headerCallback);
别忘了返回值:该回调必须返回传入 $header 的字节长度,否则 cURL 会中断请求。
curl_errno —— 看似请求发出去了,其实卡在 TLS 握手阶段,连服务器日志都收不到记录。











