PHP项目cURL与HTTP请求

wen PHP项目 1

本文目录导读:

PHP项目cURL与HTTP请求

  1. cURL基础使用
  2. 常用cURL选项
  3. 封装cURL函数
  4. 文件上传
  5. 并发请求
  6. 错误处理和调试
  7. 使用Guzzle替代cURL
  8. 最佳实践

我来详细介绍PHP中cURL和HTTP请求的使用方法。

cURL基础使用

基本GET请求

// 初始化cURL
$ch = curl_init();
// 设置URL
curl_setopt($ch, CURLOPT_URL, "https://api.example.com/data");
// 返回响应而不是直接输出
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// 执行请求
$response = curl_exec($ch);
// 检查错误
if(curl_errno($ch)) {
    echo 'cURL Error: ' . curl_error($ch);
}
// 关闭cURL
curl_close($ch);

POST请求

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.example.com/submit");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
// POST数据
$data = array(
    'username' => 'john',
    'password' => 'secret123'
);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
$response = curl_exec($ch);
curl_close($ch);

JSON数据POST

$data = array(
    'name' => 'John Doe',
    'email' => 'john@example.com'
);
$jsonData = json_encode($data);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://api.example.com/users");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-Type: application/json',
    'Content-Length: ' . strlen($jsonData)
));
$response = curl_exec($ch);
curl_close($ch);

常用cURL选项

基本配置

$ch = curl_init();
// 超时设置
curl_setopt($ch, CURLOPT_TIMEOUT, 30); // 30秒超时
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); // 连接超时
// SSL验证
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
// 跟随重定向
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_MAXREDIRS, 5);
// 自定义User-Agent
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');
// 自定义头部
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Authorization: Bearer your_token_here',
    'Accept: application/json'
));

处理Cookie

// 保存cookie到文件
$cookieFile = tempnam('/tmp', 'cookie');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://example.com/login");
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFile);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieFile);
// 登录请求
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'username=test&password=123');
$response = curl_exec($ch);
// 后续请求会自动携带cookie
curl_setopt($ch, CURLOPT_URL, "https://example.com/dashboard");
$response = curl_exec($ch);
curl_close($ch);

封装cURL函数

通用HTTP请求函数

class HttpClient {
    public static function get($url, $headers = []) {
        return self::request('GET', $url, null, $headers);
    }
    public static function post($url, $data = [], $headers = []) {
        return self::request('POST', $url, $data, $headers);
    }
    public static function put($url, $data = [], $headers = []) {
        return self::request('PUT', $url, $data, $headers);
    }
    public static function delete($url, $headers = []) {
        return self::request('DELETE', $url, null, $headers);
    }
    private static function request($method, $url, $data = null, $headers = []) {
        $ch = curl_init();
        // 基本设置
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        // 设置请求方法
        switch ($method) {
            case 'POST':
                curl_setopt($ch, CURLOPT_POST, true);
                if ($data) {
                    curl_setopt($ch, CURLOPT_POSTFIELDS, is_array($data) ? http_build_query($data) : $data);
                }
                break;
            case 'PUT':
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
                if ($data) {
                    curl_setopt($ch, CURLOPT_POSTFIELDS, is_array($data) ? json_encode($data) : $data);
                }
                break;
            case 'DELETE':
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
                break;
        }
        // 设置头部
        if (!empty($headers)) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        }
        // 执行请求
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);
        if ($error) {
            return [
                'success' => false,
                'error' => $error,
                'http_code' => $httpCode
            ];
        }
        return [
            'success' => true,
            'data' => $response,
            'http_code' => $httpCode
        ];
    }
}
// 使用示例
$result = HttpClient::get('https://api.example.com/users');
$result = HttpClient::post('https://api.example.com/users', ['name' => 'John'], [
    'Content-Type: application/json'
]);

文件上传

使用cURL上传文件

function uploadFile($url, $filePath, $fieldName = 'file') {
    if (!file_exists($filePath)) {
        return ['success' => false, 'error' => 'File not found'];
    }
    $ch = curl_init();
    // PHP 5.5+ 使用 CURLFile
    $cFile = new CURLFile($filePath, mime_content_type($filePath), basename($filePath));
    $postData = [
        $fieldName => $cFile,
        // 其他字段
        'description' => 'Test upload'
    ];
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    return [
        'success' => $httpCode == 200,
        'data' => $response,
        'http_code' => $httpCode
    ];
}

并发请求

使用curl_multi进行并发

function multiRequest($urls) {
    $multi = curl_multi_init();
    $channels = [];
    // 创建多个cURL句柄
    foreach ($urls as $key => $url) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_multi_add_handle($multi, $ch);
        $channels[$key] = $ch;
    }
    // 执行所有请求
    $active = null;
    do {
        $mrc = curl_multi_exec($multi, $active);
    } while ($mrc == CURLM_CALL_MULTI_PERFORM);
    while ($active && $mrc == CURLM_OK) {
        if (curl_multi_select($multi) == -1) {
            usleep(100);
        }
        do {
            $mrc = curl_multi_exec($multi, $active);
        } while ($mrc == CURLM_CALL_MULTI_PERFORM);
    }
    // 获取结果
    $results = [];
    foreach ($channels as $key => $ch) {
        $results[$key] = curl_multi_getcontent($ch);
        curl_multi_remove_handle($multi, $ch);
    }
    curl_multi_close($multi);
    return $results;
}
// 使用示例
$urls = [
    'google' => 'https://www.google.com',
    'github' => 'https://www.github.com',
    'php' => 'https://www.php.net'
];
$results = multiRequest($urls);

错误处理和调试

完整的错误处理

function safeCurlRequest($url, $options = []) {
    $defaults = [
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_MAXREDIRS => 5,
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_VERBOSE => true // 启用详细输出用于调试
    ];
    $ch = curl_init();
    curl_setopt_array($ch, $defaults + $options);
    // 收集调试信息
    $verbose = fopen('php://temp', 'w+');
    curl_setopt($ch, CURLOPT_STDERR, $verbose);
    $response = curl_exec($ch);
    // 错误检查
    $error = curl_error($ch);
    $errno = curl_errno($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    // 获取调试信息
    rewind($verbose);
    $verboseLog = stream_get_contents($verbose);
    curl_close($ch);
    if ($error) {
        return [
            'success' => false,
            'error' => $error,
            'errno' => $errno,
            'http_code' => $httpCode,
            'verbose' => $verboseLog
        ];
    }
    return [
        'success' => true,
        'data' => $response,
        'http_code' => $httpCode,
        'info' => curl_getinfo($ch)
    ];
}

使用Guzzle替代cURL

GuzzleHTTP库示例

// 安装: composer require guzzlehttp/guzzle
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
$client = new Client([
    'base_uri' => 'https://api.example.com',
    'timeout' => 30,
    'headers' => [
        'Accept' => 'application/json',
        'User-Agent' => 'MyApp/1.0'
    ]
]);
// GET请求
try {
    $response = $client->get('/users', [
        'query' => ['page' => 1, 'limit' => 10]
    ]);
    $body = $response->getBody();
    $data = json_decode($body, true);
} catch (RequestException $e) {
    if ($e->hasResponse()) {
        $statusCode = $e->getResponse()->getStatusCode();
        $errorBody = $e->getResponse()->getBody();
    }
}
// POST请求
$response = $client->post('/users', [
    'json' => [
        'name' => 'John',
        'email' => 'john@example.com'
    ]
]);
// 并发请求
$promises = [
    'users' => $client->getAsync('/users'),
    'posts' => $client->getAsync('/posts'),
];
$results = GuzzleHttp\Promise\Utils::unwrap($promises);

最佳实践

  1. 使用try-catch:始终包含错误处理
  2. 设置超时:避免请求挂起
  3. 验证SSL:生产环境保持启用
  4. 重用cURL句柄:提高性能
  5. 记录日志:便于调试
  6. 使用连接池:大量请求时复用连接

选择cURL还是Guzzle取决于项目需求:

  • cURL:更底层,控制更精细
  • Guzzle:更现代,功能更丰富,适合复杂场景

抱歉,评论功能暂时关闭!