当前位置: 首页 > news >正文

PHPcURL与HTTP请求实战指南

PHP cURL与HTTP请求实战指南

PHP的cURL扩展是发送HTTP请求的标准方式。它支持各种协议、认证方式、SSL证书验证等。今天说说cURL的各种用法。

先看最基本的GET请求。curl_init初始化一个cURL会话,curl_setopt设置选项,curl_exec执行请求,curl_close关闭会话。

```php
// 基本的GET请求
$ch = curl_init('https://api.example.com/users');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

if (curl_errno($ch)) {
echo "cURL错误: " . curl_error($ch) . "\n";
} else {
echo "HTTP状态码: $httpCode\n";
echo "响应时间: " . curl_getinfo($ch, CURLINFO_TOTAL_TIME) . "秒\n";
echo "响应内容: $response\n";
}

curl_close($ch);
?>
```

封装一个HTTP客户端,方便复用:

```php
class HttpClient
{
private array $defaultOptions = [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_MAXREDIRS => 5,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_USERAGENT => 'PHP HttpClient/1.0',
];

private array $headers = [];

public function setHeader(string $name, string $value): void
{
$this->headers[$name] = $value;
}

public function setHeaders(array $headers): void
{
foreach ($headers as $name => $value) {
$this->headers[$name] = $value;
}
}

public function get(string $url, array $query = []): array
{
if (!empty($query)) {
$url .= (strpos($url, '?') === false ? '?' : '&') . http_build_query($query);
}
return $this->request('GET', $url);
}

public function post(string $url, mixed $data = []): array
{
return $this->request('POST', $url, $data);
}

public function put(string $url, mixed $data = []): array
{
return $this->request('PUT', $url, $data);
}

public function delete(string $url): array
{
return $this->request('DELETE', $url);
}

private function request(string $method, string $url, mixed $data = null): array
{
$ch = curl_init($url);
$options = $this->defaultOptions;

// 设置请求方法
switch (strtoupper($method)) {
case 'POST':
$options[CURLOPT_POST] = true;
break;
case 'PUT':
$options[CURLOPT_CUSTOMREQUEST] = 'PUT';
break;
case 'DELETE':
$options[CURLOPT_CUSTOMREQUEST] = 'DELETE';
break;
case 'HEAD':
$options[CURLOPT_NOBODY] = true;
break;
}

// 设置请求体
if ($data !== null) {
if (is_array($data)) {
$options[CURLOPT_POSTFIELDS] = http_build_query($data);
} else {
$options[CURLOPT_POSTFIELDS] = $data;
$this->headers['Content-Type'] = 'application/json';
}
}

// 设置请求头
if (!empty($this->headers)) {
$headerLines = [];
foreach ($this->headers as $name => $value) {
$headerLines[] = "$name: $value";
}
$options[CURLOPT_HTTPHEADER] = $headerLines;
}

curl_setopt_array($ch, $options);
$body = curl_exec($ch);

$result = [
'body' => $body,
'http_code' => curl_getinfo($ch, CURLINFO_HTTP_CODE),
'content_type' => curl_getinfo($ch, CURLINFO_CONTENT_TYPE),
'total_time' => curl_getinfo($ch, CURLINFO_TOTAL_TIME),
'error' => curl_error($ch),
'errno' => curl_errno($ch),
];

curl_close($ch);
return $result;
}
}

// 使用
$client = new HttpClient();
$client->setHeaders([
'Accept' => 'application/json',
'Authorization' => 'Bearer token123',
]);

$result = $client->get('https://jsonplaceholder.typicode.com/posts', ['userId' => 1]);
echo "状态码: {$result['http_code']}\n";
if ($result['http_code'] === 200) {
$posts = json_decode($result['body'], true);
echo "获取到 " . count($posts) . " 篇文章\n";
}
?>
```

发送JSON格式的POST请求:

```php
$client = new HttpClient();
$client->setHeader('Content-Type', 'application/json');
$client->setHeader('Accept', 'application/json');
$client->setHeader('Authorization', 'Bearer your-api-key');

$data = [
'title' => 'Test Post',
'body' => 'This is a test post body',
'userId' => 1,
];

$result = $client->post('https://jsonplaceholder.typicode.com/posts', json_encode($data));
echo "状态码: {$result['http_code']}\n";

if ($result['http_code'] === 201) {
$response = json_decode($result['body'], true);
echo "创建成功, ID: {$response['id']}\n";
}
?>
```

文件上传用cURL也很方便:

```php
function uploadFile(string $url, string $filePath, string $fieldName = 'file'): array
{
if (!file_exists($filePath)) {
throw new RuntimeException("文件不存在: $filePath");
}

$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => [
$fieldName => curl_file_create($filePath, mime_content_type($filePath), basename($filePath)),
],
CURLOPT_TIMEOUT => 60,
]);

$body = curl_exec($ch);
$result = [
'body' => $body,
'http_code' => curl_getinfo($ch, CURLINFO_HTTP_CODE),
'error' => curl_error($ch),
];

curl_close($ch);
return $result;
}

// 批量请求
function batchRequest(array $requests): array
{
$multi = curl_multi_init();
$handles = [];

foreach ($requests as $id => $request) {
$ch = curl_init($request['url']);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);

if (!empty($request['method'] ?? 'GET')) {
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $request['method']);
}
if (!empty($request['data'])) {
curl_setopt($ch, CURLOPT_POSTFIELDS, $request['data']);
}

curl_multi_add_handle($multi, $ch);
$handles[$id] = $ch;
}

// 执行所有请求
$running = null;
do {
curl_multi_exec($multi, $running);
curl_multi_select($multi);
} while ($running > 0);

// 收集结果
$results = [];
foreach ($handles as $id => $ch) {
$results[$id] = [
'body' => curl_multi_getcontent($ch),
'http_code' => curl_getinfo($ch, CURLINFO_HTTP_CODE),
'error' => curl_error($ch),
];
curl_multi_remove_handle($multi, $ch);
curl_close($ch);
}

curl_multi_close($multi);
return $results;
}

$requests = [
'users' => ['url' => 'https://jsonplaceholder.typicode.com/users'],
'posts' => ['url' => 'https://jsonplaceholder.typicode.com/posts'],
'comments' => ['url' => 'https://jsonplaceholder.typicode.com/comments'],
];

$results = batchRequest($requests);
foreach ($results as $name => $result) {
$data = json_decode($result['body'], true);
echo "$name: 获取到 " . count($data) . " 条记录\n";
}
?>
```

cURL还支持SSL验证、代理、Cookie等高级功能:

```php
class AdvancedHttpClient
{
private array $options;

public function __construct(array $config = [])
{
$this->options = [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => $config['timeout'] ?? 30,
CURLOPT_COOKIEJAR => $config['cookie_jar'] ?? '/tmp/cookies.txt',
CURLOPT_COOKIEFILE => $config['cookie_file'] ?? '/tmp/cookies.txt',
];

// SSL配置
if (!empty($config['ssl_cert'])) {
$this->options[CURLOPT_SSLCERT] = $config['ssl_cert'];
$this->options[CURLOPT_SSLCERTPASSWD] = $config['ssl_cert_pass'] ?? '';
}

// 代理配置
if (!empty($config['proxy'])) {
$this->options[CURLOPT_PROXY] = $config['proxy'];
$this->options[CURLOPT_PROXYPORT] = $config['proxy_port'] ?? 8080;

if (!empty($config['proxy_user'])) {
$this->options[CURLOPT_PROXYUSERPWD] = $config['proxy_user'] . ':' . $config['proxy_pass'];
}
}

// 认证配置
if (!empty($config['auth'])) {
$this->options[CURLOPT_HTTPAUTH] = CURLAUTH_BASIC | CURLAUTH_DIGEST;
$this->options[CURLOPT_USERPWD] = $config['auth'];
}
}

public function download(string $url, string $savePath): bool
{
$fp = fopen($savePath, 'w');
if ($fp === false) {
throw new RuntimeException("无法写入文件: $savePath");
}

$ch = curl_init($url);
curl_setopt_array($ch, $this->options + [
CURLOPT_FILE => $fp,
CURLOPT_FOLLOWLOCATION => true,
]);

curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);

curl_close($ch);
fclose($fp);

if ($error) {
throw new RuntimeException("下载失败: $error");
}

return $httpCode === 200;
}
}

$downloader = new AdvancedHttpClient(['timeout' => 120]);
try {
$result = $downloader->download('https://example.com/file.zip', '/tmp/file.zip');
echo "下载完成\n";
} catch (RuntimeException $e) {
echo "错误: {$e->getMessage()}\n";
}
?>
```

cURL的错误处理很关键。常见的错误有超时、连接失败、SSL验证失败等。curl_errno和curl_error可以获取错误信息。

```php
function checkCurlError(int $errno, string $error): string
{
$errors = [
CURLE_COULDNT_RESOLVE_HOST => '无法解析主机名',
CURLE_COULDNT_CONNECT => '无法连接服务器',
CURLE_OPERATION_TIMEDOUT => '请求超时',
CURLE_SSL_CONNECT_ERROR => 'SSL连接错误',
CURLE_SSL_CERTPROBLEM => 'SSL证书问题',
CURLE_HTTP_RETURNED_ERROR => 'HTTP返回错误',
CURLE_SEND_ERROR => '发送数据失败',
CURLE_RECV_ERROR => '接收数据失败',
];

return $errors[$errno] ?? "未知错误($errno): $error";
}
?>
```

cURL在PHP开发中很常用。对接第三方API、抓取网页内容、上传下载文件,都离不开它。用好cURL能让你在处理HTTP请求时事半功倍。

http://www.jsqmd.com/news/940056/

相关文章:

  • GD32F330时钟树实战工程:含多源切换、PLL配置与外设时钟分配
  • 2026年靠谱的江西柔软助剂/江西皂洗助剂公司哪家好 - 品牌宣传支持者
  • 为什么你的Claude总在关键节点“随机跳转”?——决策树分支坍缩现象的3种检测工具与2小时修复流程
  • Persimmon-8B-Chat vs 其他开源模型:在昇腾平台上的对比评测
  • 3个步骤解决ComfyUI自定义节点安装失败的终极指南
  • 加密推理大揭秘:重放、侧信道能否提取模型秘密?提供商该如何应对?
  • AI Agent 面试题 906:客服Agent的个性化服务和用户画像应用
  • CANN EasyAsc DSL a2 Cube-Vec-Cube-Vec模式
  • TradingAgents-CN智能交易框架实战指南:5步快速搭建多智能体量化分析平台
  • 2026年热门的无锡电子污水处理/印染污水处理公司哪家好 - 品牌宣传支持者
  • 03 华为 harmonyos tcp 客户端 实现使用 模拟器亲测可行
  • llama-160m-openmind开发者指南:自定义训练与模型微调
  • 高数函数定义域避坑指南:从‘狗不能为零’到‘整体思想’,手把手教你识别并解决3大易错题型
  • 保姆级教程:在银河麒麟V10 SP3 ARM64服务器上,用yum downloadonly搞定Docker 26.1离线安装包
  • 建筑平台JS逆向
  • YOLOv5中文标签实战:用自定义数据集训练一个‘中文版‘安全帽检测模型(附完整代码)
  • 手把手教你用Wireshark抓包,搞定CANoe‘No TCP/IP Stack’模式下的数据监控
  • STM32F407调试神器:用CubeMX+Keil5快速搞定串口printf打印(避坑指南)
  • 数据科学实战:从问题定义到成果展示的完整项目流程解析
  • 2026年比较好的屠宰污水处理/无锡深度污水处理/中水回用污水处理优质公司推荐 - 行业平台推荐
  • 数字权益卡:企业营销新利器
  • Matlab一键运行的PSO优化BP神经网络回归预测工具包(含示例数据与全流程可视化)
  • 保姆级教程:用UE5材质系统手搓一个下雨天水坑的真实涟漪(附完整节点图)
  • 抖音直播数据抓取神器:5分钟快速上手实时弹幕监控工具
  • Linux下用libuvc驱动USB摄像头:从权限问题到实时视频流的保姆级避坑指南
  • OpCore-Simplify:智能硬件识别与自动化EFI配置引擎深度解析
  • 技术行动与学术传承:从数据密集型研究到区域创新生态构建
  • 为什么ChatGLM、LLaMA都用RoPE,而不用ALiBi?从模型选型实战聊聊位置编码的取舍
  • AD7705高精度模数转换硬件设计全套源文件(Altium工程含多版PCB与原理图)
  • BitCPM-CANN与MiniCPM4对比:三值量化模型vs全精度模型的全面性能评估