PHP:具有相同URL的多个cURL

时间:2017-03-15 17:17:01

标签: php forms curl

我的网站上有一个表单,通过cURL调用web服务,提交后发布数据。

这种情况很有效,除非在一种情况下,当远程Web服务服务器关闭时(经常发生) 所以我试图开发一个缓存系统,其工作原理如下:

  • 如果表单提交的curl执行返回false,我将其保存在数据库中
  • 我每天都在运行一个CRON工作来检查我是否有一些失败的提交
  • 我正在对结果集进行预测并为每个提交内容运行curl调用

问题是如何进行最后一步? URL始终是相同的(每次调用只更改POST字段)我想检查每个调用是否有效(让我们想象一下,在第一次提交后,远程服务器会停止运行,我想保存在我的调用中数据库,前10个是好的但不是其他的左边)

我试过这个功能,我发现:

function curl_multiRequest($data, $options = array()) {

  // array of curl handles
  $curly = array();
  // data to be returned
  $result = array();

  // multi handle
  $mh = curl_multi_init();

  // loop through $data and create curl handles
  // then add them to the multi-handle
  foreach ($data as $id => $d) {

    $curly[$id] = curl_init();

    $url = (is_array($d) && !empty($d['url'])) ? $d['url'] : $d;

    curl_setopt($curly[$id], CURLOPT_URL,            $url);
    curl_setopt($curly[$id], CURLOPT_HEADER,         0);
    curl_setopt($curly[$id], CURLOPT_RETURNTRANSFER, 1);

    // post?
    if (is_array($d)) {
      if (!empty($d['post'])) {
        curl_setopt($curly[$id], CURLOPT_POST,       1);
        curl_setopt($curly[$id], CURLOPT_POSTFIELDS, $d['post']);
      }
    }

    // extra options?
    if (!empty($options)) {
      curl_setopt_array($curly[$id], $options);
    }

    curl_multi_add_handle($mh, $curly[$id]);
  }

  // execute the handles
  $running = null;
  do {
    curl_multi_exec($mh, $running);
  } while($running > 0);


  // get content and remove handles
  foreach($curly as $id => $c) {
    $result[$id] = curl_multi_getcontent($c);
    curl_multi_remove_handle($mh, $c);
  }

  // all done
  curl_multi_close($mh);

  return $result;
}

我的数组看起来像:

    array(5) {
  [0]=>
  array(6) {
    ["id"]=>
    string(1) "7"
    ["post"]=>
    string(1644) "Surname=Test&Name=Test"
    ["url"]=>
    string(28) "http://www.mywebsite.fr/"
  }
  [1]=>
  array(6) {
    ["id"]=>
    string(1) "6"
    ["post"]=>
    string(1644) "Surname=Test1&Name=Test1"
    ["url"]=>
    string(28) "http://www.mywebsite.fr/"
  }
  [2]=>
  array(6) {
    ["id"]=>
    string(1) "5"
     ["post"]=>
    string(1644) "Surname=Test2&Name=Test2"
    ["url"]=>
    string(28) "http://www.mywebsite.fr/"
  }

}

但是当URL无效时(我尝试使用无效的URL来模拟服务器)我有这个:

    Fatal error: Maximum execution time of 30 seconds exceeded in /home/www/myscript.php on line 63

Warning: (null)(): 560 is not a valid cURL handle resource in Unknown on line 0

我做错了吗?

谢谢

编辑1:我试图实施这样的主教回答:

$myarray=array(
    array(
        "id"=>"1",
        "post"=>"Surname=Test&Name=Test",
        "url"=>"http://www.mywebsite.fr/",
    )
  ,  array(
        "id"=>"1",
        "post"=>"Surname=Test&Name=Test",
        "url"=>"http://www.mywebsite.fr/",
    )
);

    $mh = curl_multi_init();
    foreach($myarray as $k=>$failed){

            $myarray[$k]["handle"] = curl_init();
            curl_setopt($myarray[$k]["handle"], CURLOPT_URL, $failed["url"]);
        curl_setopt($myarray[$k]["handle"], CURLOPT_POST, true);
            curl_setopt($myarray[$k]["handle"], CURLOPT_POSTFIELDS, $failed["post"]);
            curl_multi_add_handle($mh, $myarray[$k]["handle"]);
        }


 foreach (multiread($mh) as $info) {
    var_dump($info);
}

但是如果远程URL无法访问,请求似乎永远不会停止。有没有办法限制每个请求执行的时间?

编辑2: 在定义选项时使用它是一种好方法吗?

curl_setopt($chs[$key], CURLOPT_CONNECTTIMEOUT , 10);

并位于脚本顶部

set_time_limit(0);

如果可以,我的最后一个问题是收集有关每个电话的信息。如何单独检索有关每个处理程序的信息(在数据库中保存此调用是否成功?)像ID一样?

1 个答案:

答案 0 :(得分:0)

您在多手柄上的循环看起来并不完整。更强大的实施:

function multiread($mh, $timeout = .5) {
    $output = array ();
    $runCnt = 0;
    do {
        // start requests, or update status of pending requests: returns by
        // reference (in $runCnt) the number of outstanding requests
        $status = curl_multi_exec($mh, $runCnt);
        if (CURLM_OK !== $status) throw new \RuntimeException;

        // take a breath, so as to not eat 100% CPU
        do {
            $status = curl_multi_select($mh, $timeout);
            if (-1 === $status) {
                usleep(10);
            }
        } while (0 === $status);

        // gather the results and yield back what we know
        while (false !== ($info = curl_multi_info_read($mh))) {
            if (CURLE_OK === $info['result']) {
                $output[] = [ $info, curl_multi_getcontent($info['handle']) ];
            } else {
                $output[] = [ $info, null ];
            }
        }
    } while (0 < $runCnt);
    return $output;
}

现在做一些循环:

$mh = curl_multi_init();
// ... add your easy handles

foreach (multiread($mh) as list ($info, $content)) {
    // $info['handle'] contains the cURL easy handle
    // $info['result'] contains the result code, see also curl_strerror
    // $content contains whatever the URL returned
}