ZetCode

PHP curl_multi_errno 函数

最后修改日期:2025 年 4 月 11 日

PHP curl_multi_errno 函数返回 cURL multi handle 的最后一个错误号。它用于识别异步 cURL 操作中的错误。此函数有助于诊断并行 HTTP 请求中的问题。

基本定义

curl_multi_errno 函数返回一个包含 cURL multi handle 最后一个错误号的整数。如果没有发生错误,它返回 0 (CURLM_OK)。

语法:curl_multi_errno(CurlMultiHandle $multi_handle): int。multi handle 必须使用 curl_multi_init() 创建。始终在 multi 操作后检查此项以检测潜在问题。

基本的 Multi Handle 错误检查

此示例演示了在初始化 multi handle 后检查错误。

basic_error_check.php
<?php

declare(strict_types=1);

$mh = curl_multi_init();

if ($mh === false) {
    die("Failed to initialize multi handle");
}

$errno = curl_multi_errno($mh);

if ($errno !== CURLM_OK) {
    echo "Multi handle error: " . curl_multi_strerror($errno);
} else {
    echo "Multi handle initialized successfully";
}

curl_multi_close($mh);

此代码初始化一个 cURL multi handle 并检查错误。我们使用 curl_multi_strerror 获取人类可读的错误消息。该示例展示了 multi handle初始化的基本错误处理。

Multi 执行中的错误处理

此示例展示了如何在 multi handle 执行期间检查错误。

multi_exec_error.php
<?php

declare(strict_types=1);

$urls = [
    "https://example.com",
    "https://nonexistent.example",
    "https://another.example"
];

$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);
    $errno = curl_multi_errno($mh);
    
    if ($errno !== CURLM_OK) {
        echo "Multi error: " . curl_multi_strerror($errno);
        break;
    }
    
    usleep(10000);
} while ($active && $status === CURLM_OK);

foreach ($handles as $ch) {
    curl_multi_remove_handle($mh, $ch);
    curl_close($ch);
}

curl_multi_close($mh);

我们创建多个 cURL handle 并将它们添加到 multi handle 中。在执行期间,我们使用 curl_multi_errno 持续检查错误。如果发生错误,循环会中断,从而阻止进一步执行有问题的请求。

处理特定的错误代码

此示例演示了如何处理 curl_multi_errno 的特定错误代码。

specific_errors.php
<?php

declare(strict_types=1);

$mh = curl_multi_init();

// Intentionally cause an error by adding a non-curl handle
$fakeHandle = fopen('php://temp', 'r');
curl_multi_add_handle($mh, $fakeHandle);

$errno = curl_multi_errno($mh);

switch ($errno) {
    case CURLM_OK:
        echo "No error occurred";
        break;
    case CURLM_BAD_HANDLE:
        echo "Error: Invalid multi handle (CURLM_BAD_HANDLE)";
        break;
    case CURLM_BAD_EASY_HANDLE:
        echo "Error: Invalid easy handle (CURLM_BAD_EASY_HANDLE)";
        break;
    case CURLM_OUT_OF_MEMORY:
        echo "Error: Out of memory (CURLM_OUT_OF_MEMORY)";
        break;
    case CURLM_INTERNAL_ERROR:
        echo "Error: Internal error (CURLM_INTERNAL_ERROR)";
        break;
    default:
        echo "Unknown error occurred: $errno";
}

if (is_resource($fakeHandle)) {
    fclose($fakeHandle);
}

curl_multi_close($mh);

我们通过将非 cURL handle 添加到 multi handle 中来故意引起错误。然后代码检查特定的错误代码并提供适当的处理。这演示了如何对各种 cURL multi 错误做出不同的响应。

并行请求中的错误处理

此示例展示了并行请求的全面错误处理。

parallel_errors.php
<?php

declare(strict_types=1);

$urls = [
    "https://valid.example.com",
    "https://invalid.example",
    "https://timeout.example.com"
];

$mh = curl_multi_init();
$handles = [];

foreach ($urls as $i =>  $url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    curl_multi_add_handle($mh, $ch);
    $handles[$i] = $ch;
}

$active = null;
do {
    $mrc = curl_multi_exec($mh, $active);
    
    if ($mrc !== CURLM_OK) {
        $errno = curl_multi_errno($mh);
        echo "Multi error: " . curl_multi_strerror($errno);
        break;
    }
    
    // Check for individual handle errors
    while ($info = curl_multi_info_read($mh)) {
        if ($info['result'] !== CURLE_OK) {
            $handle = $info['handle'];
            $errno = curl_errno($handle);
            echo "Handle error: " . curl_strerror($errno) . "\n";
        }
    }
    
    usleep(10000);
} while ($active);

foreach ($handles as $ch) {
    curl_multi_remove_handle($mh, $ch);
    curl_close($ch);
}

curl_multi_close($mh);

此示例执行带有全面错误处理的并行请求。我们同时检查 multi handle 错误和单个 handle 错误。代码演示了如何处理在并行执行期间可能发生的各种类型的错误。

与 curl_multi_strerror 结合使用

此示例展示了如何将 curl_multi_errno 与 curl_multi_strerror 结合使用。

with_strerror.php
<?php

declare(strict_types=1);

function executeMultiRequests(array $urls): void {
    $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;
    }
    
    $active = null;
    do {
        $status = curl_multi_exec($mh, $active);
        
        if ($status !== CURLM_OK) {
            $errno = curl_multi_errno($mh);
            $errorMsg = curl_multi_strerror($errno);
            throw new RuntimeException("cURL multi error: $errorMsg ($errno)");
        }
        
        usleep(10000);
    } while ($active);
    
    foreach ($handles as $ch) {
        $content = curl_multi_getcontent($ch);
        echo "Content length: " . strlen($content) . "\n";
        curl_multi_remove_handle($mh, $ch);
        curl_close($ch);
    }
    
    curl_multi_close($mh);
}

try {
    executeMultiRequests([
        "https://example.com",
        "https://example.org"
    ]);
} catch (RuntimeException $e) {
    echo "Error: " . $e->getMessage();
}

我们将 multi handle 操作包装在一个在出错时抛出异常的函数中。curl_multi_strerror 提供了一个人类可读的错误消息。这种方法为复杂的 multi 请求场景创建了更清晰的错误处理。

最佳实践

来源

PHP curl_multi_errno 文档

本教程介绍了 PHP curl_multi_errno 函数,并通过实际示例展示了其在并行 cURL 操作错误处理中的用法。

作者

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

所有 PHP cURL 教程列表。