ZetCode

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 请求。

basic_multi.php
<?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。

处理多个请求中的错误

此示例展示了在处理多个请求时如何处理错误。

error_handling.php
<?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 数组包含一个我们检查错误的返回码。对于失败的请求,我们输出错误消息。成功的请求显示响应长度。

使用回调处理响应

此示例演示了如何使用回调来处理已完成的请求。

callback_processing.php
<?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 数组和响应内容。这种方法有助于组织复杂的响应处理逻辑。处理后会执行清理。

跟踪多个请求的进度

此示例展示了如何在执行多个请求时跟踪进度。

progress_tracking.php
<?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 函数来检测完成情况。这提供了关于进度的实时反馈。总数有助于用户了解完成情况。

处理大量请求

此示例演示了如何高效地处理大量请求。

batch_processing.php
<?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 个,以更好地管理资源。在移至下一批之前,我们会执行和处理每一批。结果会存储以供后续分析。这种方法可以防止大型请求集导致系统过载。

最佳实践

来源

PHP curl_multi_info_read 文档

本教程通过实际示例介绍了 PHP curl_multi_info_read 函数,展示了并行请求处理和结果处理。

作者

我叫 Jan Bodnar,是一名充满激情的程序员,拥有丰富的编程经验。我自 2007 年开始撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在编程教学方面拥有超过十年的经验。

所有 PHP cURL 教程列表。