当前位置: 首页 > 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.gsyq.cn/news/1451470.html

相关文章:

  • 2026年靠谱的江西柔软助剂/江西皂洗助剂公司哪家好 - 品牌宣传支持者
  • 3个步骤解决ComfyUI自定义节点安装失败的终极指南
  • AI Agent 面试题 906:客服Agent的个性化服务和用户画像应用
  • 加密推理大揭秘:重放、侧信道能否提取模型秘密?提供商该如何应对?
  • 03 华为 harmonyos tcp 客户端 实现使用 模拟器亲测可行
  • 2026年热门的无锡电子污水处理/印染污水处理公司哪家好 - 品牌宣传支持者
  • llama-160m-openmind开发者指南:自定义训练与模型微调
  • 2026年比较好的屠宰污水处理/无锡深度污水处理/中水回用污水处理优质公司推荐 - 行业平台推荐
  • AD7705高精度模数转换硬件设计全套源文件(Altium工程含多版PCB与原理图)
  • BitCPM-CANN与MiniCPM4对比:三值量化模型vs全精度模型的全面性能评估
  • 分立元器件(阻容感)
  • STM32F103RCT6门禁系统源码包:支持RFID刷卡+数字密码双开,带温湿度监测与OLED菜单交互
  • Java课设可用的纯Swing宿舍管理系统(含源码、数据库脚本和界面截图)
  • 云计算如何重塑药物发现:从虚拟筛选到分子动力学的实战指南
  • Jetson Orin Nano:安装Jetpack等基础工具并验证摄像头
  • 2026年靠谱的源头厂货中板/江西外销供货中板/定制代工出口中板/江西OEM代工中板优质厂家汇总推荐 - 品牌宣传支持者
  • 实践1: Linux 系统运维环境搭建与自动化实践
  • 蓝桥杯单片机DS1302时钟显示乱跳?一个中断保护开关就搞定
  • CST时域求解器仿真不收敛?别慌,手把手教你调优Accuracy和Maximum Duration
  • 2026年热门的高性价比工厂中板/外贸出口中板/江西外销供货中板/OEM代工出口中板厂家综合对比分析 - 行业平台推荐
  • 如何快速掌握NS-USBLoader:Switch游戏管理的终极解决方案
  • 嵌入式开发实战:为ARM板子交叉编译BlueZ 5.66及其全套依赖库(含glib、dbus、libical)
  • 第七阶段:企业级项目实战核心能力(121天)Vue微前端实战:基于qiankun整合多Vue项目(主应用+子应用通信+样式隔离)
  • 45 美元一次性付费,Transmit 文件传输应用凭啥这么值?
  • Claude Code 100个真实案例 - 用AI做BIM建筑信息模型查看器(Three.js 3D展示)
  • Translumo:打破语言壁垒的Windows实时屏幕翻译神器
  • 游戏开发者的向量实战手册:从Unity中的角色移动到Shader编程,向量到底怎么用?
  • 保姆级教程:用Canmv IDE给K210开发板烧录.bin和.kmodel文件(附串口连接避坑指南)
  • Python自动化获取雅虎/Stooq行情+蒙特卡洛模拟投资组合收益分布
  • 高中生科研实习:如何平衡热情与技能,在前沿科技项目中脱颖而出