PHP curl_multi_info_read 函数
最后修改日期:2025 年 4 月 11 日
PHP curl_multi_info_read
函数读取已完成 cURL 操作的信息。它与 curl_multi_exec 一起用于并行处理多个传输。此函数有助于跟踪已完成的请求。
基本定义
curl_multi_info_read
函数从 multi handle 读取已完成传输的信息。它返回一个信息数组或 FALSE。
语法:curl_multi_info_read(CurlMultiHandle $multi_handle, int &$queued_messages = null): array|false
。必须反复调用该函数,直到它返回 FALSE。
基础多请求
此示例演示了如何并行执行多个 cURL 请求。
<?php declare(strict_types=1); $urls = [ "https://jsonplaceholder.typicode.com/posts/1", "https://jsonplaceholder.typicode.com/posts/2", "https://jsonplaceholder.typicode.com/posts/3" ]; $mh = curl_multi_init(); $handles = []; foreach ($urls as $url) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_multi_add_handle($mh, $ch); $handles[] = $ch; } do { $status = curl_multi_exec($mh, $active); if ($active) { curl_multi_select($mh); } } while ($active && $status == CURLM_OK); while ($info = curl_multi_info_read($mh)) { $ch = $info['handle']; $content = curl_multi_getcontent($ch); echo "Completed request: " . curl_getinfo($ch, CURLINFO_EFFECTIVE_URL) . "\n"; echo "Status: " . $info['result'] . "\n"; echo "Response length: " . strlen($content) . " bytes\n\n"; curl_multi_remove_handle($mh, $ch); curl_close($ch); } curl_multi_close($mh);
此代码并行执行三个请求。我们使用 curl_multi_info_read 来获取已完成请求的信息。结果包含 handle 和状态码。处理后我们会清理 handle。
处理多个请求中的错误
此示例展示了在处理多个请求时如何处理错误。
<?php declare(strict_types=1); $urls = [ "https://jsonplaceholder.typicode.com/posts/1", "https://invalid.url.xyz", "https://jsonplaceholder.typicode.com/posts/3" ]; $mh = curl_multi_init(); $handles = []; foreach ($urls as $url) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_multi_add_handle($mh, $ch); $handles[$url] = $ch; } do { $status = curl_multi_exec($mh, $active); if ($active) { curl_multi_select($mh); } } while ($active && $status == CURLM_OK); while ($info = curl_multi_info_read($mh)) { $ch = $info['handle']; $url = array_search($ch, $handles, true); if ($info['result'] !== CURLE_OK) { echo "Error for $url: " . curl_error($ch) . "\n"; } else { $content = curl_multi_getcontent($ch); echo "Success for $url: " . strlen($content) . " bytes\n"; } curl_multi_remove_handle($mh, $ch); curl_close($ch); } curl_multi_close($mh);
我们处理包括无效 URL 在内的多个 URL。info 数组包含一个我们检查错误的返回码。对于失败的请求,我们输出错误消息。成功的请求显示响应长度。
使用回调处理响应
此示例演示了如何使用回调来处理已完成的请求。
<?php declare(strict_types=1); function process_response(array $info, $content) { $url = curl_getinfo($info['handle'], CURLINFO_EFFECTIVE_URL); $code = curl_getinfo($info['handle'], CURLINFO_HTTP_CODE); echo "URL: $url\n"; echo "Status: $code\n"; echo "Content length: " . strlen($content) . "\n"; echo "cURL result: " . $info['result'] . "\n\n"; } $urls = [ "https://jsonplaceholder.typicode.com/posts/1", "https://jsonplaceholder.typicode.com/posts/2", "https://jsonplaceholder.typicode.com/posts/3" ]; $mh = curl_multi_init(); $handles = []; foreach ($urls as $url) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_multi_add_handle($mh, $ch); $handles[] = $ch; } do { $status = curl_multi_exec($mh, $active); if ($active) { curl_multi_select($mh); } } while ($active && $status == CURLM_OK); while ($info = curl_multi_info_read($mh)) { $content = curl_multi_getcontent($info['handle']); process_response($info, $content); curl_multi_remove_handle($mh, $info['handle']); curl_close($info['handle']); } curl_multi_close($mh);
我们定义了一个回调函数来处理每个已完成的请求。回调接收 info 数组和响应内容。这种方法有助于组织复杂的响应处理逻辑。处理后会执行清理。
跟踪多个请求的进度
此示例展示了如何在执行多个请求时跟踪进度。
<?php declare(strict_types=1); $urls = [ "https://jsonplaceholder.typicode.com/posts/1", "https://jsonplaceholder.typicode.com/posts/2", "https://jsonplaceholder.typicode.com/posts/3" ]; $mh = curl_multi_init(); $handles = []; $completed = 0; $total = count($urls); foreach ($urls as $url) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_NOPROGRESS, false); curl_multi_add_handle($mh, $ch); $handles[] = $ch; } do { $status = curl_multi_exec($mh, $active); // Check for completed requests while ($info = curl_multi_info_read($mh)) { $completed++; echo "Completed $completed of $total requests\n"; curl_multi_remove_handle($mh, $info['handle']); curl_close($info['handle']); } if ($active) { curl_multi_select($mh); } } while ($active && $status == CURLM_OK); curl_multi_close($mh); echo "All requests completed\n";
我们在执行过程中跟踪已完成请求的数量。在循环中调用 info_read 函数来检测完成情况。这提供了关于进度的实时反馈。总数有助于用户了解完成情况。
处理大量请求
此示例演示了如何高效地处理大量请求。
<?php declare(strict_types=1); // Generate 100 sample URLs $urls = array_map(function($i) { return "https://jsonplaceholder.typicode.com/posts/" . ($i + 1); }, range(0, 99)); $mh = curl_multi_init(); $handles = []; $batchSize = 10; $results = []; // Process in batches to avoid overwhelming the system for ($i = 0; $i < count($urls); $i += $batchSize) { $batch = array_slice($urls, $i, $batchSize); // Add batch to multi handle foreach ($batch as $url) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_multi_add_handle($mh, $ch); $handles[$url] = $ch; } // Execute batch do { $status = curl_multi_exec($mh, $active); if ($active) { curl_multi_select($mh); } } while ($active && $status == CURLM_OK); // Process completed requests while ($info = curl_multi_info_read($mh)) { $ch = $info['handle']; $url = array_search($ch, $handles, true); $results[$url] = [ 'status' => $info['result'], 'content' => curl_multi_getcontent($ch) ]; curl_multi_remove_handle($mh, $ch); curl_close($ch); unset($handles[$url]); } } curl_multi_close($mh); echo "Processed " . count($results) . " requests\n"; echo "Success rate: " . (count(array_filter($results, fn($r) => $r['status'] === CURLE_OK)) / count($results) * 100 . "%\n";
我们将 100 个请求分批处理,每批 10 个,以更好地管理资源。在移至下一批之前,我们会执行和处理每一批。结果会存储以供后续分析。这种方法可以防止大型请求集导致系统过载。
最佳实践
- 错误检查:始终检查 info 数组中的返回码。
- 资源清理:处理后移除并关闭 handle。
- 批量处理:将大型请求集分批处理。
- 进度反馈:为长时间操作提供进度更新。
- 内存管理:及时释放资源以避免泄漏。
来源
本教程通过实际示例介绍了 PHP curl_multi_info_read
函数,展示了并行请求处理和结果处理。