PHP curl_multi_remove_handle
函数
最后修改日期:2025 年 4 月 11 日
PHP curl_multi_remove_handle
函数从一个 multi handle 中移除一个 cURL handle。它用于并发请求处理,以便在 multi-handle 上下文中管理单个 handle。
基本定义
curl_multi_remove_handle
函数从一个 multi handle 中移除一个标准的 cURL handle。这通常在 handle 完成其请求后进行。该函数成功时返回 0,失败时返回 CURLM_* 错误代码。
语法:curl_multi_remove_handle(CurlMultiHandle $multi_handle, CurlHandle $handle): int
。两个 handle 都必须是有效且已初始化的。始终在关闭 handle 之前移除它们,以防止资源泄露。
基本的 Multi Handle 移除
此示例演示了从 multi handle 中移除 handle 的基本用法。
<?php declare(strict_types=1); $mh = curl_multi_init(); $ch1 = curl_init('https://api.example.com/data1'); $ch2 = curl_init('https://api.example.com/data2'); curl_multi_add_handle($mh, $ch1); curl_multi_add_handle($mh, $ch2); // Execute the multi handle $running = null; do { curl_multi_exec($mh, $running); } while ($running > 0); // Remove handles after completion curl_multi_remove_handle($mh, $ch1); curl_multi_remove_handle($mh, $ch2); curl_multi_close($mh); curl_close($ch1); curl_close($ch2);
此代码创建一个 multi handle 并添加两个 cURL handle。在执行所有请求后,它在关闭每个 handle 之前正确地移除它们。这可以防止资源泄露并确保干净的清理。
选择性 Handle 移除
此示例展示了如何根据响应状态选择性地移除 handle。
<?php declare(strict_types=1); $mh = curl_multi_init(); $handles = []; for ($i = 1; $i <= 5; $i++) { $ch = curl_init("https://jsonplaceholder.typicode.com/posts/$i"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_multi_add_handle($mh, $ch); $handles[] = $ch; } do { curl_multi_exec($mh, $running); curl_multi_select($mh); } while ($running > 0); foreach ($handles as $handle) { $httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE); if ($httpCode === 200) { $response = curl_multi_getcontent($handle); echo "Success: " . substr($response, 0, 50) . "...\n"; } curl_multi_remove_handle($mh, $handle); curl_close($handle); } curl_multi_close($mh);
我们创建多个请求并并发处理它们。完成后,我们检查每个响应状态,并且只输出成功的响应。无论状态如何,所有 handle 都被正确移除和关闭。
移除时的错误处理
此示例演示了移除 handle 时的正确错误处理。
<?php declare(strict_types=1); $mh = curl_multi_init(); $ch1 = curl_init('https://invalid.url'); $ch2 = curl_init('https://jsonplaceholder.typicode.com/posts/1'); curl_multi_add_handle($mh, $ch1); curl_multi_add_handle($mh, $ch2); do { curl_multi_exec($mh, $running); curl_multi_select($mh); } while ($running > 0); // Process and remove handles $handles = [$ch1, $ch2]; foreach ($handles as $handle) { $errno = curl_errno($handle); if ($errno !== 0) { echo "Error: " . curl_error($handle) . "\n"; } else { echo "Success: " . substr(curl_multi_getcontent($handle), 0, 50) . "...\n"; } $result = curl_multi_remove_handle($mh, $handle); if ($result !== CURLM_OK) { echo "Warning: Failed to remove handle (" . curl_multi_strerror($result) . ")\n"; } curl_close($handle); } curl_multi_close($mh);
我们处理成功和失败的请求。代码检查 cURL 错误,并验证移除操作是否成功。这确保了在生产环境中具有强大的错误处理能力。
动态 Handle 管理
此示例展示了在执行过程中动态添加和移除 handle。
<?php declare(strict_types=1); $mh = curl_multi_init(); $activeHandles = 0; function addRequest($mh, &$activeHandles, $url) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_multi_add_handle($mh, $ch); $activeHandles++; return $ch; } // Initial requests $ch1 = addRequest($mh, $activeHandles, 'https://jsonplaceholder.typicode.com/posts/1'); $ch2 = addRequest($mh, $activeHandles, 'https://jsonplaceholder.typicode.com/posts/2'); do { curl_multi_exec($mh, $running); // Check for completed requests while ($info = curl_multi_info_read($mh)) { if ($info['msg'] === CURLMSG_DONE) { $handle = $info['handle']; echo "Completed: " . curl_getinfo($handle, CURLINFO_EFFECTIVE_URL) . "\n"; curl_multi_remove_handle($mh, $handle); curl_close($handle); $activeHandles--; // Add new request when one completes if ($activeHandles < 2) { $newId = rand(3, 10); addRequest($mh, $activeHandles, "https://jsonplaceholder.typicode.com/posts/$newId"); } } } curl_multi_select($mh); } while ($activeHandles > 0); curl_multi_close($mh);
此代码维护一个活动请求池。当一个请求完成时,它会被移除,然后添加一个新的请求。此模式对于有速率限制的 API 或处理大量 URL 非常有用。
复杂的 Multi Handle 场景
此示例演示了一个包含不同请求类型的复杂场景。
<?php declare(strict_types=1); $mh = curl_multi_init(); $handles = []; // Create GET requests for ($i = 1; $i <= 3; $i++) { $ch = curl_init("https://jsonplaceholder.typicode.com/posts/$i"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_multi_add_handle($mh, $ch); $handles[] = ['type' => 'GET', 'handle' => $ch]; } // Create POST request $postData = json_encode(['title' => 'foo', 'body' => 'bar', 'userId' => 1]); $ch = curl_init("https://jsonplaceholder.typicode.com/posts"); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $postData, CURLOPT_HTTPHEADER => ['Content-Type: application/json'] ]); curl_multi_add_handle($mh, $ch); $handles[] = ['type' => 'POST', 'handle' => $ch]; // Process all requests do { curl_multi_exec($mh, $running); curl_multi_select($mh); } while ($running > 0); // Process responses and clean up foreach ($handles as $item) { $ch = $item['handle']; $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); echo "{$item['type']} request to " . curl_getinfo($ch, CURLINFO_EFFECTIVE_URL); echo " returned $httpCode\n"; curl_multi_remove_handle($mh, $ch); curl_close($ch); } curl_multi_close($mh);
此示例在同一个 multi handle 中混合了 GET 和 POST 请求。每个请求都与其类型一起跟踪,以便正确处理。执行后,所有 handle 都被正确移除和关闭,展示了全面的资源管理。
最佳实践
- 始终移除 Handle: 在关闭之前移除,以防止泄露。
- 检查移除结果: 验证 curl_multi_remove_handle 是否成功。
- 顺序很重要: 在关闭 handle 之前移除它们。
- 错误处理: 同时检查执行和移除错误。
- 资源跟踪: 在复杂场景中跟踪 handle。
来源
PHP curl_multi_remove_handle 文档
本教程通过实际示例介绍了 PHP curl_multi_remove_handle
函数,展示了其在各种并发请求场景中的用法。