-1

Please, how to convert the following code to async GuzzleHttp? In this way, php is waiting for the return of each query.

while ($p = pg_fetch_array($var)) {
    $url = "https://url";

    $curl = curl_init($url);
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

    $headers = array("Content-Type: application/json");
    curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);

    $data = '{"s1":"s1","number":"'.$p['number'].'"}';

    curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);

    $resp = curl_exec($curl);
    curl_close($curl);
    var_dump($resp);
}
misterxis
  • 61
  • 1
  • 8
  • 1
    PHP does not support `async`/`await`. It doesn't support multithreading by default either, you need to configure your PHP installation (including compiling from source, if necessary) to enable `pthreads`. – Dai Nov 15 '20 at 03:05
  • PHP's continued lack of support for asynchronicity is one of the reasons why Node.JS is so popular today: web developers migrated over from PHP to JS+NodeJS+etc. It's a warning to other language-vendors: embrace the latest paradigm-shifts or be condemned to be like Java or Cobol. And no-one wants to be like Java today. – Dai Nov 15 '20 at 03:06
  • @Dai not sure about Postgres, but PHP's MySQLi supports async, for example this will run 3 SELECT queries in parallel async: ```$db->query("SELECT 1",MYSQLI_ASYNC | MYSQLI_STORE_RESULT);$db->query("SELECT 1",MYSQLI_ASYNC | MYSQLI_STORE_RESULT);$db->query("SELECT 1",MYSQLI_ASYNC | MYSQLI_STORE_RESULT);$db->reap_async_query();$db->reap_async_query();$db->reap_async_query();``` (unfortunately, PDO does not support async. if you want to use async with MySQL in PHP, you need to use MySQLi, not PDO - in my opinion, this is the *only* thing MySQLi does better than PDO: async support.) – hanshenrik Nov 15 '20 at 10:32
  • @hanshenrik Right, but that's not PHP doing that, that's the MySQL client managing its own threads. – Dai Nov 15 '20 at 10:41
  • @Dai right (actually its not threading based, it's based on multiple tcp sockets and select()/async socket reading, it's about how the MySQL client is handling it's sockets, not it's threads. could also mention that PHP isn't using the official libmysqlclient, they used to, back in PHP 5.3, but then threw it out and created their own home-made client for performance reasons) - in any case there's 2 things here that can be done async, #1: fetching the data from postgres, and #2: fetching the data from https://url, and php can do both of these async (the pg_ api has an async api, and curl_multi) – hanshenrik Nov 15 '20 at 10:51
  • 2
    **[You should not switch off `CURLOPT_SSL_VERIFYHOST` or `CURLOPT_SSL_VERIFYPEER`](https://paragonie.com/blog/2017/10/certainty-automated-cacert-pem-management-for-php-software)**. It could be a security risk! [Here is how to get the certificate bundle if your server is missing one](https://stackoverflow.com/a/32095378/1839439) – Dharman Nov 15 '20 at 13:32

2 Answers2

0

Here's a working example using native curl_multi_*() functions. Specifically:

<?php
$urls = ['https://example.com/', 'https://google.com'];

$handles = [];

foreach ($urls as $url) {
    $handle = curl_init();
    curl_setopt($handle, CURLOPT_URL, $url);
    curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);

    $handles[] = $handle;
}

$multiHandle = curl_multi_init();

foreach ($handles as $handle) {
    curl_multi_add_handle($multiHandle, $handle);
}
for(;;){
    curl_multi_exec($multiHandle, $stillRunning);
    if($stillRunning > 0){
        // some handles are still downloading, sleep-wait for data to arrive
        curl_multi_select($multiHandle);
    }else{
        // all downloads completed
        break;
    }
}

foreach ($handles as $handle) {
    $result = curl_multi_getcontent($handle);
    var_dump($result);
    curl_multi_remove_handle($multiHandle, $handle);
}

curl_multi_close($multiHandle);

hanshenrik
  • 19,904
  • 4
  • 43
  • 89
Petr Hejda
  • 40,554
  • 8
  • 72
  • 100
  • 1
    don't use a busyloop for curl_multi, it will use 100% cpu (of 1 core) while downloading, for no good reason. instead do: ```for(;;){curl_multi_exec($multiHandle, $stillRunning);if($stillRunning < 1){/*all downloads completed*/break;}else{/*some handles are still downloading, sleep-wait for data to arrive*/curl_multi_select($multiHandle,1);}}``` - instead of 100% cpu, it will use some 1-2% cpu, and be no slower. – hanshenrik Nov 15 '20 at 17:10
0

Now, how convert the code cUrl to GuzzleHttp?

misterxis
  • 61
  • 1
  • 8