首页 > 解决方案 > 在 foreach 循环上执行 cURL 请求,交替返回 http 代码 200 和 0

问题描述

我有一个使用 curl_multi_excec 函数的代码,但它返回 http 代码 200 和 0,这意味着交替。这是我的代码片段:

try{
        $allproducts = json_decode(self::getProductbyEan());

        //An array that will contain all of the information
        //relating to each request.
        $requests = array();


        //Initiate a multiple cURL handle
        $mh = curl_multi_init();

        //Loop through each URL.
        foreach($allproducts as $k => $url){

            $url = 'https://nartastaging.retailpath.com.au/cgi-bin/WebObjects/NARTAStaging.woa/ra/Product/'.$url->id.'.json';
            $requests[$k] = array();
            $requests[$k]['url'] = $url;
            //Create a normal cURL handle for this particular request.
            $requests[$k]['curl_handle'] = curl_init($url);
            //Configure the options for this request.
            curl_setopt($requests[$k]['curl_handle'], CURLOPT_RETURNTRANSFER, true);
            curl_setopt($requests[$k]['curl_handle'], CURLOPT_FOLLOWLOCATION, true);
            curl_setopt($requests[$k]['curl_handle'], CURLOPT_TIMEOUT, 10);
            curl_setopt($requests[$k]['curl_handle'], CURLOPT_CONNECTTIMEOUT, 10);
            curl_setopt($requests[$k]['curl_handle'], CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($requests[$k]['curl_handle'], CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($requests[$k]['curl_handle'], CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
            curl_setopt($requests[$k]['curl_handle'], CURLOPT_USERPWD, "$login:$password");
            //Add our normal / single cURL handle to the cURL multi handle.
            curl_multi_add_handle($mh, $requests[$k]['curl_handle']);

        }

        //Execute our requests using curl_multi_exec.
        $stillRunning = false;
        curl_multi_setopt ( $mh , CURLMOPT_MAXCONNECTS, 5);
        do {

            curl_multi_exec($mh, $stillRunning);

        } while ($stillRunning);

        //Loop through the requests that we executed.
        foreach($requests as $k => $request){
            //Remove the handle from the multi handle.
            curl_multi_remove_handle($mh, $request['curl_handle']);
            //Get the response content and the HTTP status code.
            $requests[$k]['http_code'] = curl_getinfo($request['curl_handle'], CURLINFO_HTTP_CODE);
            //Close the handle.
            curl_close($requests[$k]['curl_handle']);
        }
        //Close the multi handle.
        curl_multi_close($mh);

        //var_dump the $requests array for example purposes.
        print_r($requests);

    }catch(Exception $e){
        wp_die($e->getMessage());
    }

这是结果的输出:

[0] => Array
    (
        [url] => https://nartastaging.retailpath.com.au/cgi-bin/WebObjects/NARTAStaging.woa/ra/Product/1155551.json
        [curl_handle] => Resource id #75
        [http_code] => 200
    )

[1] => Array
    (
        [url] => https://nartastaging.retailpath.com.au/cgi-bin/WebObjects/NARTAStaging.woa/ra/Product/6345345334.json
        [curl_handle] => Resource id #76
        [http_code] => 0
    )

[2] => Array
    (
        [url] => https://nartastaging.retailpath.com.au/cgi-bin/WebObjects/NARTAStaging.woa/ra/Product/45456456.json
        [curl_handle] => Resource id #77
        [http_code] => 200
    )

[3] => Array
    (
        [url] => https://nartastaging.retailpath.com.au/cgi-bin/WebObjects/NARTAStaging.woa/ra/Product/145555.json
        [curl_handle] => Resource id #78
        [http_code] => 0
    )

[4] => Array
    (
        [url] => https://nartastaging.retailpath.com.au/cgi-bin/WebObjects/NARTAStaging.woa/ra/Product/2qw22w.json
        [curl_handle] => Resource id #79
        [http_code] => 200
    )

[5] => Array
    (
        [url] => https://nartastaging.retailpath.com.au/cgi-bin/WebObjects/NARTAStaging.woa/ra/Product/5025155024034.json
        [curl_handle] => Resource id #80
        [http_code] => 0
    )

[6] => Array
    (
        [url] => https://nartastaging.retailpath.com.au/cgi-bin/WebObjects/NARTAStaging.woa/ra/Product/5025155023983.json
        [curl_handle] => Resource id #81
        [http_code] => 200
    )

如您所见,http_code 结果显示在某些情况下它返回 200 和 0。任何帮助将不胜感激。提前致谢

标签: phpcurl

解决方案


我重构了您的代码以使其更易于理解。此外,我使用免费的外部 API 来检查代码。到目前为止,我没有看到任何问题。也许问题就在你$url身边(' https://nartastaging.retailpath.com.au/cgi-bin/WebObjects/NARTA ...')。我的意思是,也许该 API 有一些检查以在并行运行时禁用某些请求......

<?php declare(strict_types=1);

final class MultiRequestForProduct
{
    /** @var string */
    private $baseUrl;

    public function __construct(string $baseUrl)
    {
        $this->baseUrl = $baseUrl;
    }

    public function execute(array $products): array
    {
        $multiCurl = $this->initMultiCurl();
        $requests = $this->initRequests($products);
        $this->execMultiCurl($multiCurl, $requests);
        $requests = $this->addHttpCodeToRequest($multiCurl, $requests);
        curl_multi_close($multiCurl);

        return $requests;
    }

    private function initMultiCurl()
    {
        $multiCurl = curl_multi_init();
        curl_multi_setopt($multiCurl, CURLMOPT_MAXCONNECTS, 2);

        return $multiCurl;
    }

    private function initRequests(array $products): array
    {
        foreach ($products as $k => $url) {
            $url = sprintf($this->baseUrl, $url->id);
            $requests[$k] = [
                'url' => $url,
                'curl_handle' => curl_init($url),
            ];
            $handler = curl_init($url);
            curl_setopt($handler, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($handler, CURLOPT_FOLLOWLOCATION, true);
            curl_setopt($handler, CURLOPT_TIMEOUT, 10);
            curl_setopt($handler, CURLOPT_CONNECTTIMEOUT, 10);
            curl_setopt($handler, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($handler, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($handler, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
//        curl_setopt($handler, CURLOPT_USERPWD, "$login:$password");
            $requests[$k]['curl_handle'] = $handler;
        }

        return $requests;
    }

    private function execMultiCurl($multiCurl, array $requests): void
    {
        foreach ($requests as $request) {
            curl_multi_add_handle($multiCurl, $request['curl_handle']);
        }

        $stillRunning = false;

        do {
            curl_multi_exec($multiCurl, $stillRunning);
        } while ($stillRunning);
    }

    private function addHttpCodeToRequest($multiCurl, array $requests): array
    {
        foreach ($requests as $k => $request) {
            curl_multi_remove_handle($multiCurl, $request['curl_handle']);
            $requests[$k]['http_code'] = curl_getinfo($request['curl_handle'], CURLINFO_HTTP_CODE);
            curl_close($requests[$k]['curl_handle']);
        }

        return $requests;
    }
}

// Usage: 
$products = [];
foreach (range(1, 8) as $i) {
    $product = new \stdClass;
    $product->id = $i;
    $products[] = $product;
}

$multiRequest = new MultiRequestForProduct($baseUrl = 'https://httpbin.org/get?id=%d');
$requests = $multiRequest->execute($products);
var_dump($requests);

推荐阅读