PHP curl_multi_getcontent возвращает null

Я curl_multi за этим руководством по использованию curl_multi . http://arguments.callee.info/2010/02/21/multiple-curl-requests-with-php/

Я не могу сказать, что я делаю неправильно, но curl_multi_getcontent возвращает null. Предполагается вернуть JSON. Я знаю, что это не вызов mysql, поскольку он работал с циклом while и стандартным curl_exec , но страница слишком долго загружалась. (Я изменил некоторые детали setopt для обеспечения безопасности)

Соответствующий фрагмент кода PHP. Я закрываю цикл while в конце.

 $i = 0; $ch = array(); $mh = curl_multi_init(); while($row = $result->fetch_object()){ $ch[$i] = curl_init(); curl_setopt($ch[$i], CURLOPT_CAINFO, 'cacert.pem'); curl_setopt($ch[$i], CURLOPT_USERPWD, "$username:$password"); curl_setopt($ch[$i], CURLOPT_RETURNTRANSFER, true); curl_setopt($ch[$i], CURLOPT_URL, 'https://mysite.com/search/'.$row->username.'/'); curl_multi_add_handle($mh, $ch[$i]); $i++; } $running = 0; do { curl_multi_exec($mh, $running); } while ($running > 0); $result->data_seek(0); $i = 0; while ($row = $result->fetch_object()) { $data = curl_multi_getcontent($ch[$i]); $json_data = json_decode($data); var_dump($json_data); 

РЕДАКТИРОВАТЬ

Вот код, который в настоящее время работает, но вызывает слишком медленную загрузку страницы

 $ch = curl_init(); curl_setopt($ch, CURLOPT_CAINFO, 'cacert.pem'); curl_setopt($ch, CURLOPT_USERPWD, "$username:$password"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); while($row = $result->fetch_object()){ curl_setopt($ch, CURLOPT_URL, 'https://mysite.com/search/'.$row->username.'/'); $data = curl_exec($ch); $json_data = json_decode($data); var_dump($json_data); } 

Related of "PHP curl_multi_getcontent возвращает null"

Мне любопытно:

 $i = 0; while ($row = $result->fetch_object()) { $data = curl_multi_getcontent($ch[$i]); $json_data = json_decode($data); var_dump($json_data); 

Забываете ли вы увеличивать $ i? Если это так, вы уже схватили контент за $ ch [0], а затем снова вызываете curl_multi_getcontent.

Кроме того, я написал сообщение в блоге о параллельных запросах с расширением cURL PHP и содержит общую функцию для зависания нескольких запросов. Вы можете вызвать эту функцию следующим образом:

 $responses = multi([ $requests = [ ['url' => 'https://mysite.com/search/username1/'], ['url' => 'https://mysite.com/search/username2/'], ['url' => 'https://mysite.com/search/username3/'] ] $opts = [ CURLOPT_CAINFO => 'cacert.pem', CURLOPT_USERPWD => "username:password" ] ]); 

Затем вы выполняете цикл ответов:

 foreach ($responses as $response) { if ($response['error'] { // handle error continue; } // check for empty response if ($response['data'] === null) { // examine $response['info'] continue; } // handle data $data = json_decode($response['data']); // do something } 

Используя эту функцию, вы можете сделать простой тест на доступ к сайтам https, используя следующий вызов:

 multi( $requests = [ 'google' => ['url' => 'https://www.google.com'], 'linkedin' => ['url'=> 'https://www.linkedin.com/'] ], $opts = [ CURLOPT_CAINFO => '/path/to/your/cacert.pem', CURLOPT_SSL_VERIFYPEER => true ] ); 

Я вижу, что ваш цикл выполнения отличается от того, который рекомендуется в документации PHP :

 do { $mrc = curl_multi_exec($mh, $active); } while ($mrc == CURLM_CALL_MULTI_PERFORM); 

Обратите внимание, что в while как возврат функции сравнивается, а не второй параметр.

Редактировать : благодаря комментарию Адама я тестировал оба синтаксиса и вижу, что они равны и асинхронны. Ниже приведен рабочий пример асинхронного многопротокола с получением содержимого в переменную:

 <?php $ch = array(); $mh = curl_multi_init(); $total = 100; echo 'Start: ' . microtime(true) . "\n"; for ($i = 0; $i < $total; $i++) { $ch[$i] = curl_init(); curl_setopt($ch[$i], CURLOPT_URL, 'http://localhost/sleep.php?t=' . $i); curl_setopt($ch[$i], CURLOPT_HEADER, 0); curl_setopt($ch[$i], CURLOPT_RETURNTRANSFER, true); curl_multi_add_handle($mh, $ch[$i]); } $active = null; do { $mrc = curl_multi_exec($mh, $active); usleep(100); // Maybe needed to limit CPU load (See PS) } while ($active); foreach ($ch AS $i => $c) { $r = curl_multi_getcontent($c); var_dump($r); curl_multi_remove_handle($mh, $c); } curl_multi_close($mh); echo 'End: ' . microtime(true) . "\n"; 

И тестирование файла sleep.php:

 <?php $start = microtime(true); sleep( rand(3, 5) ); $end = microtime(true); echo $_GET['t'], ': ', $start, ' - ', $end, ' - ', ($end - $start); echo "\n"; 

PS Первоначальная идея использования usleep внутри цикла заключалась в том, чтобы немного приостановить его и, следовательно, уменьшить количество операций, в то время как cUrl ожидает ответа. И вначале это работало именно так. Но последние тесты с top показали минимальную разницу в загрузке процессора (17% с usleep против 20% без него). Поэтому я не знаю, использовать это или нет. Возможно, тесты на реальном сервере покажут другие результаты.

Редактирование 2 : я проверил свой код с запросом на страницу HTTPS с защитой паролем ( CURLOPT_CAINFO и CURLOPT_USERPWD равные тем, которые CURLOPT_USERPWD в вопросе). Он работает так, как ожидалось. Вероятно, есть ошибка в вашей версии PHP или cURL. Мои версии: «Версия PHP 5.3.10-1ubuntu3.8» и 7.22.0. У них нет проблем.

curl_multi_exec выполняет curl_multi_exec HTTP-запросы и запросы, которые могут быть выполнены не для того, чтобы вы добавили их в мультиплексор $mh . Чтобы получить ответ от выполненных запросов, вы должны использовать функцию curl_multi_info_read . Вы можете узнать больше об этом на php.net http://php.net/manual/ru/function.curl-multi-info-read.php

Вы установили для CURLOPT_SSL_VERIFYPEER значение true?

Используйте $running = null; вместо $running = 0; ,

По ссылкам:

  1. множественные скручивание-запросы-с-PHP

  2. http://www.php.net/manual/en/function.curl-multi-exec.php

В обоих случаях переменная была определена как NULL, это потому, что

 curl_multi_exec ( resource $mh , int &$still_running ) 

Второй аргумент – ссылка на переменную.

Кроме того, вы можете найти это полезным: php single curl works, но multi curl не работает