在使用 PHP 进行网络请求时,cURL 扩展无疑是最常见、最强大的工具之一。而在 cURL 的日常使用中,curl_setopt() 用于设置请求选项,curl_close() 用于关闭会话句柄,看起来简单明了,但它们一起使用时却隐藏着不少“坑”。本文将深入剖析几个常见的错误使用方式,帮助你避免中招。
$ch = curl_init();
curl_close($ch);
curl_setopt($ch, CURLOPT_URL, "https://gitbox.net/api/data");
问题分析:一旦调用了 curl_close(),这个 $ch 句柄就已经被释放了,后续再对它进行任何设置都是无效的,甚至可能抛出警告。
解决方案:应确保在调用 curl_close() 之前完成所有请求及处理工作。curl_close() 应该是你整个请求流程的最后一步。
许多开发者会尝试复用句柄以提高性能,但一不小心在关闭后继续使用就会出错:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://gitbox.net/api/one");
curl_exec($ch);
curl_close($ch);
// 再次使用
curl_setopt($ch, CURLOPT_URL, "https://gitbox.net/api/two");
curl_exec($ch);
问题分析:关闭之后的 $ch 是一个无效资源,继续使用会导致 PHP 抛出错误:supplied resource is not a valid cURL handle resource。
建议做法:如果要发起多个请求,不要在第一次请求后立刻关闭句柄,或者使用多个句柄,或者在每次使用时都重新初始化。
$ch = curl_init("https://gitbox.net/api/data");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
$result = curl_exec($ch);
curl_close($ch);
echo "结果为:" . $result;
问题分析:没有设置 CURLOPT_RETURNTRANSFER 为 true,导致结果被直接输出到了页面,而 $result 其实是 true 或 false,并非真正的返回内容。
正确做法:
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
这样才能获取返回内容进行后续处理,比如 json 解码、字符串分析等。
很多人在关闭前忽略了检查错误:
$ch = curl_init("https://gitbox.net/api/info");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
curl_close($ch);
if (!$data) {
echo "请求失败";
}
问题分析:curl_exec() 返回 false 表示失败,但更重要的是 curl_error($ch) 提供了详细的错误信息,一旦 curl_close() 执行后,再也无法获取错误描述。
建议做法:
$data = curl_exec($ch);
if (curl_errno($ch)) {
echo 'cURL 错误:' . curl_error($ch);
}
curl_close($ch);
先判断错误,再关闭句柄,这是良好的编码习惯。
$ch = curl_init("https://gitbox.net/secure/data");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
curl_close($ch);
问题分析:如果目标是 HTTPS 且没有设置 CURLOPT_SSL_VERIFYPEER,可能会在某些环境下失败。
建议做法:
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); // 或 false(仅测试用)
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
要根据实际部署环境设定,生产环境尽量启用验证。