PHP curl_reset函数

定义和用法

curl_reset() 函数用于重置cURL句柄的所有选项到默认值。这个函数在需要复用同一个cURL句柄进行多个不同请求时非常有用,可以避免重复创建和销毁句柄的开销。

注意:此函数在PHP 5.5.0及以上版本可用。

语法

curl_reset ( CurlHandle $handle ) : void

参数

参数 描述
handle curl_init() 返回的 cURL 句柄。

返回值

该函数没有返回值。

示例

示例 1:基本用法 - 复用cURL句柄

// 初始化cURL句柄
$ch = curl_init();

// 第一次请求:获取网页内容
curl_setopt_array($ch, [
    CURLOPT_URL => 'https://httpbin.org/get',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERAGENT => 'First Request Agent'
]);

$response1 = curl_exec($ch);
echo "第一次请求状态码: " . curl_getinfo($ch, CURLINFO_HTTP_CODE) . "\n";

// 重置cURL句柄
curl_reset($ch);

// 第二次请求:使用不同的选项
curl_setopt_array($ch, [
    CURLOPT_URL => 'https://httpbin.org/post',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => ['key' => 'value'],
    CURLOPT_USERAGENT => 'Second Request Agent'
]);

$response2 = curl_exec($ch);
echo "第二次请求状态码: " . curl_getinfo($ch, CURLINFO_HTTP_CODE) . "\n";

// 清理
curl_close($ch);

示例 2:在循环中复用cURL句柄

function makeMultipleRequests($urls) {
    $ch = curl_init();
    $results = [];

    // 设置公共选项(这些会在每次reset后保留)
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

    foreach ($urls as $index => $url) {
        // 注意:CURLOPT_URL需要在每次迭代中重新设置
        curl_setopt($ch, CURLOPT_URL, $url);

        $results[$index] = [
            'url' => $url,
            'response' => curl_exec($ch),
            'http_code' => curl_getinfo($ch, CURLINFO_HTTP_CODE),
            'error' => curl_error($ch)
        ];

        // 重置句柄以备下次使用(但保留基本选项)
        // 注意:curl_reset会重置所有选项,包括RETURNTRANSFER等
        // 所以在这个例子中,我们选择不reset,而是只修改URL
        // 如果需要完全不同的配置,可以使用reset

        echo "请求 {$index}: {$url} - HTTP {$results[$index]['http_code']}\n";
    }

    curl_close($ch);
    return $results;
}

// 使用示例
$urls = [
    'https://httpbin.org/get',
    'https://httpbin.org/status/200',
    'https://httpbin.org/status/404',
    'https://httpbin.org/status/500'
];

$results = makeMultipleRequests($urls);

示例 3:正确使用curl_reset的场景

class ApiClient {
    private $ch;
    private $baseOptions = [];

    public function __construct($baseUrl = '') {
        $this->ch = curl_init();
        $this->baseOptions = [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_FOLLOWLOCATION => true
        ];

        if ($baseUrl) {
            $this->baseOptions[CURLOPT_URL] = $baseUrl;
        }
    }

    public function get($endpoint, $headers = []) {
        // 重置到初始状态
        curl_reset($this->ch);

        // 设置基础选项
        curl_setopt_array($this->ch, $this->baseOptions);

        // 设置GET特定选项
        if ($endpoint) {
            curl_setopt($this->ch, CURLOPT_URL, $this->baseOptions[CURLOPT_URL] . $endpoint);
        }
        curl_setopt($this->ch, CURLOPT_HTTPGET, true);

        if (!empty($headers)) {
            curl_setopt($this->ch, CURLOPT_HTTPHEADER, $headers);
        }

        return $this->execute();
    }

    public function post($endpoint, $data, $headers = []) {
        // 重置到初始状态
        curl_reset($this->ch);

        // 设置基础选项
        curl_setopt_array($this->ch, $this->baseOptions);

        // 设置POST特定选项
        if ($endpoint) {
            curl_setopt($this->ch, CURLOPT_URL, $this->baseOptions[CURLOPT_URL] . $endpoint);
        }
        curl_setopt($this->ch, CURLOPT_POST, true);
        curl_setopt($this->ch, CURLOPT_POSTFIELDS, $data);

        if (!empty($headers)) {
            curl_setopt($this->ch, CURLOPT_HTTPHEADER, $headers);
        }

        return $this->execute();
    }

    public function put($endpoint, $data, $headers = []) {
        curl_reset($this->ch);
        curl_setopt_array($this->ch, $this->baseOptions);

        if ($endpoint) {
            curl_setopt($this->ch, CURLOPT_URL, $this->baseOptions[CURLOPT_URL] . $endpoint);
        }
        curl_setopt($this->ch, CURLOPT_CUSTOMREQUEST, 'PUT');
        curl_setopt($this->ch, CURLOPT_POSTFIELDS, $data);

        if (!empty($headers)) {
            curl_setopt($this->ch, CURLOPT_HTTPHEADER, $headers);
        }

        return $this->execute();
    }

    private function execute() {
        $response = curl_exec($this->ch);

        return [
            'response' => $response,
            'http_code' => curl_getinfo($this->ch, CURLINFO_HTTP_CODE),
            'error' => curl_error($this->ch),
            'info' => curl_getinfo($this->ch)
        ];
    }

    public function __destruct() {
        if ($this->ch) {
            curl_close($this->ch);
        }
    }
}

// 使用示例
$client = new ApiClient('https://httpbin.org');

// 执行GET请求
$result1 = $client->get('/get');
echo "GET请求: HTTP {$result1['http_code']}\n";

// 执行POST请求
$result2 = $client->post('/post', ['key' => 'value']);
echo "POST请求: HTTP {$result2['http_code']}\n";

// 执行PUT请求
$result3 = $client->put('/put', json_encode(['data' => 'test']), ['Content-Type: application/json']);
echo "PUT请求: HTTP {$result3['http_code']}\n";

示例 4:性能对比 - 使用reset vs 创建新句柄

// 测试使用curl_reset的性能
function testWithReset($urls) {
    $start = microtime(true);
    $ch = curl_init();

    foreach ($urls as $url) {
        curl_reset($ch);
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 10
        ]);
        curl_exec($ch);
    }

    curl_close($ch);
    return microtime(true) - $start;
}

// 测试创建新句柄的性能
function testWithNewHandle($urls) {
    $start = microtime(true);

    foreach ($urls as $url) {
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 10
        ]);
        curl_exec($ch);
        curl_close($ch);
    }

    return microtime(true) - $start;
}

// 准备测试数据
$testUrls = array_fill(0, 50, 'https://httpbin.org/get');

// 执行性能测试
$timeWithReset = testWithReset($testUrls);
$timeWithNewHandle = testWithNewHandle($testUrls);

echo "使用curl_reset耗时: " . round($timeWithReset, 4) . " 秒\n";
echo "创建新句柄耗时: " . round($timeWithNewHandle, 4) . " 秒\n";
echo "性能提升: " . round((1 - $timeWithReset / $timeWithNewHandle) * 100, 2) . "%\n";

示例 5:处理复杂选项的重置

function complexRequestWithReset() {
    $ch = curl_init();

    // 第一次请求:设置复杂选项
    curl_setopt_array($ch, [
        CURLOPT_URL => 'https://httpbin.org/post',
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => http_build_query(['complex' => 'data']),
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/x-www-form-urlencoded',
            'User-Agent: CustomAgent/1.0',
            'X-Custom-Header: value'
        ],
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_VERBOSE => true,
        CURLOPT_HEADER => true
    ]);

    echo "第一次请求配置:\n";
    echo "URL: " . curl_getinfo($ch, CURLINFO_EFFECTIVE_URL) . "\n";
    echo "POST: " . (curl_getinfo($ch, CURLINFO_REQUEST_SIZE) > 0 ? '是' : '否') . "\n";

    $response1 = curl_exec($ch);
    echo "第一次请求完成,HTTP状态码: " . curl_getinfo($ch, CURLINFO_HTTP_CODE) . "\n\n";

    // 重置所有选项
    curl_reset($ch);

    echo "重置后的配置:\n";
    echo "URL: " . (curl_getinfo($ch, CURLINFO_EFFECTIVE_URL) ?: '未设置') . "\n";
    echo "POST: " . (curl_getinfo($ch, CURLINFO_REQUEST_SIZE) > 0 ? '是' : '否') . "\n\n";

    // 第二次请求:完全不同的配置
    curl_setopt_array($ch, [
        CURLOPT_URL => 'https://httpbin.org/get',
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPGET => true,
        CURLOPT_USERAGENT => 'SimpleAgent',
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_MAXREDIRS => 5
    ]);

    echo "第二次请求配置:\n";
    echo "URL: " . curl_getinfo($ch, CURLINFO_EFFECTIVE_URL) . "\n";
    echo "GET: " . (curl_getinfo($ch, CURLINFO_REQUEST_SIZE) == 0 ? '是' : '否') . "\n";

    $response2 = curl_exec($ch);
    echo "第二次请求完成,HTTP状态码: " . curl_getinfo($ch, CURLINFO_HTTP_CODE) . "\n";

    curl_close($ch);

    return [$response1, $response2];
}

// 执行示例
list($resp1, $resp2) = complexRequestWithReset();

curl_reset vs curl_close + curl_init

方面 curl_reset curl_close + curl_init
性能 更高效,复用连接 较低,需要重新建立连接
内存使用 较少,复用资源 较多,频繁分配释放
使用场景 需要复用句柄进行类似请求 完全不同的请求配置
代码简洁性 更简洁 需要更多代码

注意事项

重要:curl_reset() 会重置所有选项到默认值,包括 CURLOPT_URLCURLOPT_RETURNTRANSFER 等。重置后需要重新设置所有必要的选项。
最佳实践:
  • 在需要复用cURL句柄进行多个不同配置的请求时使用 curl_reset()
  • 对于相同配置的多个请求,不需要使用 curl_reset(),只需修改必要的选项(如URL)
  • 使用面向对象的方式封装cURL操作,可以更好地管理句柄生命周期
注意事项:curl_reset() 不会关闭连接,只是重置选项。如果需要重新建立连接,应该使用 curl_close()curl_init()

常见问题

Q: curl_reset() 会重置哪些选项?

A: curl_reset() 会将cURL句柄的所有选项重置到默认值,就像刚刚调用 curl_init() 一样。这包括URL、HTTP方法、头信息、超时设置等所有选项。

Q: 什么时候应该使用curl_reset()?

A: 当你需要复用同一个cURL句柄进行多个配置完全不同的请求时,应该使用 curl_reset()。如果只是修改URL等少量选项,不需要重置。

Q: curl_reset() 会影响性能吗?

A: 正确使用 curl_reset() 可以提升性能,因为它避免了重复创建和销毁cURL句柄的开销。但在只需要修改少量选项的场景中,直接修改选项而不重置可能更高效。

相关函数