前言
cURL 是 PHP 中最常用的网络请求工具,可以模拟浏览器向远程服务器发起 HTTP 请求,常用于调用第三方 API、抓取网页、上传下载文件等场景。本文基于 libcurl 扩展,整理常用函数和参数。
基本流程
使用 cURL 固定四步:初始化、设置选项、执行、关闭。
<?php
// 1. 初始化
$ch = curl_init();
// 2. 设置选项
curl_setopt($ch, CURLOPT_URL, 'https://example.com/api');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 返回结果而不是直接输出
// 3. 执行请求
$response = curl_exec($ch);
// 4. 关闭句柄
curl_close($ch);
echo $response;
CURLOPT_RETURNTRANSFER 必须重点记住:设为 true 时 curl_exec 返回字符串;不设置则直接把结果打印到页面。
常用选项详解
基础选项
curl_setopt($ch, CURLOPT_URL, 'https://example.com'); // 请求地址
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 以字符串返回结果
curl_setopt($ch, CURLOPT_HEADER, false); // 是否返回响应头
curl_setopt($ch, CURLOPT_TIMEOUT, 10); // 整个请求超时秒数
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3); // 连接超时秒数
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 跟随 302 跳转
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0'); // 自定义 UA
curl_setopt($ch, CURLOPT_REFERER, 'https://example.com'); // 伪造 referer
GET 请求
GET 参数直接拼在 URL 上:
<?php
$data = ['name' => 'Tom', 'age' => 20];
$url = 'https://example.com/api?' . http_build_query($data);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
POST 请求
<?php
$ch = curl_init('https://example.com/api');
$postData = ['username' => 'admin', 'password' => '123456'];
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($postData), // 表单方式
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
curl_close($ch);
两种 POSTFIELDS 写法的区别:
- 传字符串(
http_build_query后):Content-Type 为application/x-www-form-urlencoded - 传数组:multipart/form-data,可用于文件上传
- 传
json_encode后的字符串:需手动设置 JSON 头
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($data, JSON_UNESCAPED_UNICODE),
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Content-Length: ' . strlen(json_encode($data)),
],
]);
自定义请求头
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer your_token',
'Accept: application/json',
]);
携带 Cookie
curl_setopt($ch, CURLOPT_COOKIE, 'name=Tom; age=20');
// 或从文件读取
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookie.txt');
HTTPS 证书问题
本地调试遇到 SSL 证书报错时,可临时关闭验证(生产环境不建议):
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
正确做法是下载 CA 证书并指定:
curl_setopt($ch, CURLOPT_CAINFO, '/etc/ssl/certs/cacert.pem');
获取响应信息与错误处理
curl_getinfo 可以拿到状态码、耗时等信息;curl_error 用于排错:
<?php
$ch = curl_init('https://example.com/api');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
if ($response === false) {
echo 'cURL 错误: ' . curl_error($ch);
} else {
$info = curl_getinfo($ch);
echo '状态码: ' . $info['http_code'] . PHP_EOL;
echo '总耗时: ' . $info['total_time'] . ' 秒' . PHP_EOL;
echo $response;
}
curl_close($ch);
注意判断要用 === false,因为返回空字符串也可能是合法响应。
上传文件
<?php
// PHP 5.5+ 推荐使用 CURLFile
$ch = curl_init('https://example.com/upload');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'file' => new CURLFile('/tmp/test.jpg', 'image/jpeg', 'test.jpg'),
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
echo curl_exec($ch);
curl_close($ch);
封装一个通用 GET/POST 函数
<?php
function http(string $url, array $data = [], string $method = 'GET'): string
{
$ch = curl_init();
$opts = [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
CURLOPT_SSL_VERIFYPEER => false,
];
if (strtoupper($method) === 'POST') {
$opts[CURLOPT_POST] = true;
$opts[CURLOPT_POSTFIELDS] = http_build_query($data);
} else {
$opts[CURLOPT_URL] = $url . (strpos($url, '?') === false ? '?' : '&')
. http_build_query($data);
}
curl_setopt_array($ch, $opts);
$response = curl_exec($ch);
curl_close($ch);
return $response ?: '';
}
// 使用示例
echo http('https://example.com/api', ['id' => 1]);
echo http('https://example.com/api', ['name' => 'Tom'], 'POST');
常见问题排查
- 返回 false:先用
curl_error看错误信息,多数是 SSL 证书或超时问题 - 中文乱码:确认对方接口返回编码,必要时
mb_convert_encoding转换 - POST 拿不到数据:检查 Content-Type 是否与发送格式匹配
- 302 后拿不到结果:加上
CURLOPT_FOLLOWLOCATION => true
小结
cURL 的核心就是 curl_init、curl_setopt、curl_exec、curl_close 四步,其余全是 CURLOPT_* 参数的组合。掌握 GET、POST、JSON、文件上传这几类典型写法,再配合 curl_error 和 curl_getinfo 排错,基本可以应对所有 HTTP 请求场景。