web-dev-qa-db-ja.com

PHPの非同期curl要求

PHPで2つのcurl postリクエストを実行しています。それらは次のようになります。

//Onfleet API credentials 
$username = 'xxxxx'; 
$api_onfleet = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';    
$url_onfleet = "https://onfleet.com/api/v2/tasks";

curl_setopt($curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
    $request =  $url.'api/mail.send.json';

    // Generate curl request
    $session = curl_init($request);
    // Tell curl to use HTTP POST
    curl_setopt ($session, CURLOPT_POST, true);
    // Tell curl that this is the body of the POST
    curl_setopt ($session, CURLOPT_POSTFIELDS, $params);
    // Tell curl not to return headers, but do return the response
    curl_setopt($session, CURLOPT_HEADER, false);
    curl_setopt($session, CURLOPT_RETURNTRANSFER, true);

    // obtain response
    $response = curl_exec($session);
    curl_close($session);


     // Post the Pickup task to Onfleet
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url_onfleet);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_USERPWD, $api_onfleet);
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
    curl_setopt($ch, CURLOPT_ENCODING, "");  
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, '{"destination":{"address":{"unparsed":"'.$pickup_address.'"},"notes":"'.$comments.'"},"recipients":[{"name":"'.$name.'","phone":"+61'.$phone.'","notes":"Number of riders: '.$riders.'"}],"completeBefore":'.$timestamp.',"pickupTask":"yes","autoAssign":{"mode":"distance"}}');

    $result_pickup = curl_exec($ch);
    curl_close($ch);

    // Post the Dropoff task to Onfleet
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url_onfleet);
    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_USERPWD, $api_onfleet);
    curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
    curl_setopt($curl, CURLOPT_ENCODING, "");  
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, '{"destination":{"address":{"unparsed":"'.$dropoff_address.'"},"notes":"'.$comments.'"},"recipients":[{"name":"'.$name.'","phone":"+61'.$phone.'","notes":"Number of riders: '.$riders.'"}],"autoAssign":{"mode":"distance"}}');

    $result_dropoff = curl_exec($curl);
    curl_close($curl);

それらは機能していますが、2番目のcurl post要求が実行されない場合があります。

この2つのリクエストを同時に実行したいと思います。

どうやってやるの?ポストフィールドでは異なるオプションを使用することに注意してください。

ご協力いただきありがとうございます!

12
Hyacinthe

したいのは、cUrlリクエストの非同期実行です。

そのため、PHP用の非同期/並列処理ライブラリが必要になります。


pThreads

PHPの有名なスレッドライブラリの1つは pthreads です。

最初にdll/soファイルを取得して_php/ext_ dirに保存し、_php.ini_でその拡張機能を有効にする必要があります。

その後、このコードはあなたの仕事をするでしょう:

_class Request1 extends Thread {
    $username = 'xxxxx'; 
    $api_onfleet = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';    
    $url_onfleet = "https://onfleet.com/api/v2/tasks";
    public function run() {
        curl_setopt($curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
        $request =  $this->url.'api/mail.send.json';

        // Generate curl request
        $session = curl_init($request);
        // Tell curl to use HTTP POST
        curl_setopt ($session, CURLOPT_POST, true);
       // Tell curl that this is the body of the POST
       curl_setopt ($session, CURLOPT_POSTFIELDS, $params);
       // Tell curl not to return headers, but do return the response
       curl_setopt($session, CURLOPT_HEADER, false);
       curl_setopt($session, CURLOPT_RETURNTRANSFER, true);

        // obtain response
        $response = curl_exec($session);
        curl_close($session);
    }
}


class Request2 extends Thread {
    $username = 'xxxxx'; 
    $api_onfleet = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';    
    $url_onfleet = "https://onfleet.com/api/v2/tasks";
    public function run() {
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_URL, $url_onfleet);
      curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
      curl_setopt($ch, CURLOPT_USERPWD, $this->api_onfleet);
      curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
      curl_setopt($ch, CURLOPT_ENCODING, "");  
      curl_setopt($ch, CURLOPT_POST, true);
      curl_setopt($ch, CURLOPT_POSTFIELDS, '{"destination":{"address":{"unparsed":"'.$pickup_address.'"},"notes":"'.$comments.'"},"recipients":[{"name":"'.$name.'","phone":"+61'.$phone.'","notes":"Number of riders: '.$riders.'"}],"completeBefore":'.$timestamp.',"pickupTask":"yes","autoAssign":{"mode":"distance"}}');

      $result_pickup = curl_exec($ch);
      curl_close($ch);

      // Post the Dropoff task to Onfleet
      $curl = curl_init();
      curl_setopt($curl, CURLOPT_URL, $this->url_onfleet);
      curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
      curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
      curl_setopt($curl, CURLOPT_USERPWD, $this->api_onfleet);
      curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
      curl_setopt($curl, CURLOPT_ENCODING, "");  
      curl_setopt($curl, CURLOPT_POST, true);
      curl_setopt($curl, CURLOPT_POSTFIELDS, '{"destination":{"address":{"unparsed":"'.$dropoff_address.'"},"notes":"'.$comments.'"},"recipients":[{"name":"'.$name.'","phone":"+61'.$phone.'","notes":"Number of riders: '.$riders.'"}],"autoAssign":{"mode":"distance"}}');

      $result_dropoff = curl_exec($curl);
      curl_close($curl);
    }
}

$req1 = new Request1();
$req1->start();
$req2 = new Request2();
$req2->start();
_

したがって、基本的にはThreadクラスを拡張するクラスを作成する必要があり、非同期で(むしろ並列に)実行するすべてのものは、クラスのrun()関数に配置されます。

スレッドを開始する場合は、変数でクラスをインスタンス化し、$threadsObject->start()などのオブジェクトのstartメソッドを呼び出すだけで、run()のすべてが別のスレッドで実行されます。

参照:

  1. _class::Thread_
  2. _Thread::start_

それでおしまい。


非同期cURL

もう1つの方法は、組み込みの 非同期cURL関数 を使用することです。

したがって、_curl_multi_*_を使用すると、コードは次のようになります。

_$username = 'xxxxx'; 
$api_onfleet = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';    
$url_onfleet = "https://onfleet.com/api/v2/tasks";

curl_setopt($curl, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
    $request =  $url.'api/mail.send.json';

    // Generate curl request
    $session = curl_init($request);
    // Tell curl to use HTTP POST
    curl_setopt ($session, CURLOPT_POST, true);
    // Tell curl that this is the body of the POST
    curl_setopt ($session, CURLOPT_POSTFIELDS, $params);
    // Tell curl not to return headers, but do return the response
    curl_setopt($session, CURLOPT_HEADER, false);
    curl_setopt($session, CURLOPT_RETURNTRANSFER, true);


     // Post the Pickup task to Onfleet
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url_onfleet);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_USERPWD, $api_onfleet);
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
    curl_setopt($ch, CURLOPT_ENCODING, "");  
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, '{"destination":{"address":{"unparsed":"'.$pickup_address.'"},"notes":"'.$comments.'"},"recipients":[{"name":"'.$name.'","phone":"+61'.$phone.'","notes":"Number of riders: '.$riders.'"}],"completeBefore":'.$timestamp.',"pickupTask":"yes","autoAssign":{"mode":"distance"}}');
$mh = curl_multi_init();
curl_multi_add_handle($mh,$session);
curl_multi_add_handle($mh,$ch);

$active = null;
//execute the handles
do {
    $mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);

while ($active && $mrc == CURLM_OK) {
    if (curl_multi_select($mh) != -1) {
        do {
            $mrc = curl_multi_exec($mh, $active);
        } while ($mrc == CURLM_CALL_MULTI_PERFORM);
    }
}
//close the handles
curl_multi_remove_handle($mh, $ch1);
curl_multi_remove_handle($mh, $ch2);
curl_multi_close($mh);
_

推奨読書:

  1. curl_multi_init()
  2. curl_multi_exec()
  3. curl_multi_add_handle()
  4. curl_multi_remove_handle()
35
Ikari