PHP asynchronous cURL with callback

19,953

Maybe take a look at this: https://gist.github.com/Xeoncross/2362936

Request:

class Requests
{
    public $handle;

    public function __construct()
    {
        $this->handle = curl_multi_init();
    }

    public function process($urls, $callback)
    {
        foreach ($urls as $url) {
            $ch = curl_init($url);
            curl_setopt_array($ch, array(CURLOPT_RETURNTRANSFER => TRUE));
            curl_multi_add_handle($this->handle, $ch);
        }

        do {
            $mrc = curl_multi_exec($this->handle, $active);

            if ($state = curl_multi_info_read($this->handle)) {
                //print_r($state);
                $info = curl_getinfo($state['handle']);
                //print_r($info);
                $callback(curl_multi_getcontent($state['handle']), $info);
                curl_multi_remove_handle($this->handle, $state['handle']);
            }

            usleep(10000); // stop wasting CPU cycles and rest for a couple ms

        } while ($mrc == CURLM_CALL_MULTI_PERFORM || $active);

    }

    public function __destruct()
    {
        curl_multi_close($this->handle);
    }
}
Share:
19,953
canibal_uruguayo
Author by

canibal_uruguayo

Updated on June 15, 2022

Comments

  • canibal_uruguayo
    canibal_uruguayo almost 2 years

    I am trying to do a request using cURL in an asynchronous way with callback. I am using a piece of code that i copy from a site.

    When i write in my browser this url: http://www.myhost:3049/exemplo/index/async/ its execute the function asyncAction thats execute the curl_post function.

    /** 
    * Send a POST requst using cURL 
    * @param string $url to request 
    * @param array $post values to send 
    * @param array $options for cURL 
    * @return string 
    */ 
    function curl_post($url, array $post = NULL, array $options = array()) 
    { 
        $defaults = array( 
            CURLOPT_POST => 1, 
            CURLOPT_HEADER => 0, 
            CURLOPT_URL => $url, 
            CURLOPT_FRESH_CONNECT => 1, 
            CURLOPT_RETURNTRANSFER => 1, 
            CURLOPT_FORBID_REUSE => 1, 
            CURLOPT_TIMEOUT => 4, 
            CURLOPT_POSTFIELDS => http_build_query($post) 
        ); 
    
        $ch = curl_init(); 
        curl_setopt_array($ch, ($options + $defaults)); 
        if( ! $result = curl_exec($ch)) 
        { 
            $result = curl_error($ch);
        } 
        curl_close($ch); 
        return $result; 
    } 
    
    
    public function asyncAction() {
        $this->curl_post("http://www.myhost:3049/exemplo/index/add/");
    }
    

    Then the cURL execute cURL to that URL to execute an action that NOW is in the same class that the others function, just for testing. This action is addAction, that just return a string with the message "CALLBACK".

    function addAction() {
        sleep(15);
        return "CALLBACK";
    }
    

    The $result is returning just false. Maybe the problem is that i am requesting trying to execute an action that is in the same class that the cURL function. But anyways, how can i get the error message. Is there any better solution, tested, and with good explanation about using as asynchronous with callback? Because the things i read are not well explained and also it does not explain when, how to manage the callback thing.

    • Barmar
      Barmar over 9 years
      The add script has to echo something.
    • Barmar
      Barmar over 9 years
      curl is not asynchronous.
    • canibal_uruguayo
      canibal_uruguayo over 9 years
      i searched in google many articles about it and i found some of them talking about asynchronous cURL. For example in this page they are talking about this: php.net/manual/pt_BR/function.curl-setopt.php
    • Barmar
      Barmar over 9 years
      I can't find the word asynchronous on that page.
    • canibal_uruguayo
      canibal_uruguayo over 9 years
      In the page i wrote it, they mention about callback function, i think that if they mentioned about to callback a function is because that is asynchronous. This article talks about it: php.net/manual/pt_BR/function.curl-setopt.php Anyways, if you are saying cURL is not asynchronous, is there any way of use asynchronous and callbacks in PHP requests?
    • Barmar
      Barmar over 9 years
      You're not using any of the options that take a callback function. But these functions are not for processing the results asynchronously, they're run synchronously by cURL.
    • canibal_uruguayo
      canibal_uruguayo over 9 years
      I know. Do you have any suggestion?
    • canibal_uruguayo
      canibal_uruguayo over 9 years
      @Barmar i dont know why you mark as duplicate. That post you suggest does not answer my question. Do you know the concept about callback with asynchronous?
    • Barmar
      Barmar over 9 years
      Yes, I understand it. But PHP doesn't have it. You could fork a child process to run your curl asynchronously, but you won't be able to get the result with a callback.
    • canibal_uruguayo
      canibal_uruguayo over 9 years
      @Barmar So, why instead of telling that, you mark the question as duplicate. Is better if you tell the answer or maybe a suggestion. It is easy to tell "PHP doesn't have it", instead of suggest any other solution or trying to really help my problem.
    • web-nomad
      web-nomad over 9 years
      See curl_multi_init (not async, but can run multiple requests in parallel). For async, you have to use Gearman (gearman.org). It's available as a php extension. Not sure, if that would help you.
    • canibal_uruguayo
      canibal_uruguayo over 9 years
      @web-nomad thanks, and do you know how to get return message from that async request?
    • web-nomad
      web-nomad over 9 years
      curl_multi_init works the same way as a curl_init, one diff being it can run multiple requests in parallel (which is same as async, not in the strict sense). You can see the doc on the php site. If you can use gearman, nothing like it.
    • canibal_uruguayo
      canibal_uruguayo over 9 years
      @web-nomad i understood but you told, but now i am asking about the return message of the async request. Is other topic that just an async function.
    • Barmar
      Barmar over 9 years
      Misunderstood what you were trying to achieve. I undid it.
    • canibal_uruguayo
      canibal_uruguayo over 9 years
      anyways, why my code does not work?
    • Barmar
      Barmar over 9 years
      Your code doesn't work because you set a 4-second timeout, and the server sleeps for 15 seconds.
    • canibal_uruguayo
      canibal_uruguayo over 9 years
      @Barmar I changed that, and i delete the TIME OUT in the curl config and did not work too. Any ideas?
  • Tejas Tank
    Tejas Tank about 9 years
    Thanks for sharing seem useful, I will sure try this.. Does it also work with cron system ?
  • Beachhouse
    Beachhouse about 9 years
    Sure, I wouldn't see a reason it wouldn't.