Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- /**
- * ACurl.php
- *
- * Run multiple cURL parallel requests in Asynchronous way
- *
- * - Uses a curl_multi handler to make the requests in parallel
- * - when response is returned from the host, the class call an
- * external callback function with the response data as a parameter
- * - The programmer defines the number of simultaneous request to prevent
- * server overload useing a queue to manipulate the remaining requests
- * after the first requests returns.
- * - And on each request returned, a new queued request is started.
- *
- * @author Wemerson C. Guimarães <[email protected]>
- * @version 0.1
- * @copyright Copyright © 2012 Wemerson C. Guimarães
- * @access public
- */
- Class ACurl{
- /**
- * Array with the sources of URLs to be loaded
- * @access private
- * @var $sources
- * @example array(
- * array(
- * "ID"=>"328",
- * "name"=>"Celebridades | Terra - Gente",
- * "url" => "http://rss.terra.com.br/0,,EI13419,00.xml"
- * ),
- * array(
- * "ID" => "304",
- * "feed" => "Notícias pelo Mundo | G1 - Mundo" ,
- * "url" => "http://g1.globo.com/dynamo/mundo/rss2.xml"
- * )
- * )
- */
- private $sources = array();
- /**
- * Last sources item index... This will be incremented on each new request queued
- * @access private
- * @var $last_index
- */
- private $last_index;
- /**
- * Qtd of simultaneous requests in parallel
- * @access private
- * @var $parallels
- */
- private $parallels;
- /**
- * The multiple cURL handle
- * @access private
- * @var $cMulti_handle
- */
- private $cMulti_handle;
- /**
- * The class Constructor
- *
- * @param Array $sources Array of URLs to be loaded
- * @param Integer $parallels Qtd of simultaneous requests in parallel
- * @param Array $custom_options User custom options
- * @todo $custom_options is not working yet... do this in the future versions
- *
- */
- public function __construct($sources=null, $parallels=5, $custom_options=null){
- // Set sources
- $this->setSources($sources);
- // Fix the max of simultaneous requests.
- $this->parallels = $parallels;
- $this->parallels = (sizeof($this->sources) < $this->parallels) ? sizeof($this->sources) : $this->parallels;
- }
- /**
- * Fill the Array of sources with the URLs
- *
- * @param Array $sources Array of URLs to be loaded
- *
- */
- public function setSources($sources){
- $this->sources = $sources;
- }
- /**
- * Run and Process the requests and each callbacks.
- *
- * @param Function $callback External asynchronous function to manipulate the response of the requests.
- * @return Array
- *
- */
- public function run($callback){
- /**
- * Create the asynchronous cURL multi-handle
- * This will receive the queue of requests
- */
- $this->cMulti_handle = curl_multi_init();
- /**
- * Fill the queue with the first requests
- * The size of queue is defined in $this->parallels
- */
- for ($this->last_index = 0; $this->last_index < $this->parallels; $this->last_index++){
- $this->createRequest($this->last_index);
- }
- /**
- * Array with the requests failed to be processed ( http_code != 200 )
- * It will be returned bye this method
- */
- $fail = array(); // URLS que tiveram retorno diferente de 200
- do {
- while(($execrun = curl_multi_exec($this->cMulti_handle, $running)) == CURLM_CALL_MULTI_PERFORM);
- if($execrun != CURLM_OK)
- break;
- /**
- * A request was completed with http_code 200 (Read OK), or any error
- */
- while($done = curl_multi_info_read($this->cMulti_handle)) {
- $info = curl_getinfo($done['handle']);
- /**
- * Find the currect URL in the sources Array,
- * Doing a foreach in $this->sources and compare
- * the handle stored in each element of the array with
- * the handle of the request response
- */
- $queue_handle = null;
- foreach($this->sources as $source){
- if($source['handle'] === $done['handle']){
- $queue_handle = $source['handle'];
- unset($source['handle']);
- $source['response_url'] = $info['url'];
- break;
- }
- }
- /**
- * Check if the response is Ok (200) and call the external callback function
- * passing the response data loaded to be processed on it
- */
- if ($info['http_code'] == 200) {
- /**
- * Do a second compare of the both handles of queued and response
- * before call a callback
- */
- if($queue_handle === $done['handle']){
- unset($source['handle']);
- $callback($source, curl_multi_getcontent($done['handle']));
- }
- /**
- * Add a new request to the queue to be processed
- */
- $this->createRequest($this->last_index++);
- }else{
- /**
- * store a response failed to be returned by this method
- * when the queue was finished
- */
- $source['http_code'] = $info['http_code'];
- array_push($fail, $source);
- }
- /**
- * Remove the handle because he is just finished.
- */
- curl_multi_remove_handle($this->cMulti_handle, $done['handle']);
- }
- } while ($running);
- /**
- * Close the cURL multi hande
- */
- curl_multi_close($this->cMulti_handle);
- /**
- * Return a array of requests with http_code != 200 or NULL
- */
- return $fail;
- }
- /**
- * Create a new request, add it in the cURL multi handle and store his handle in
- * the sources array.
- *
- * @param Integer $i Last sources item index
- *
- */
- private function createRequest($i){
- if($i > count($this->sources) - 1)
- return false;
- /**
- * Start a new handle
- */
- $current = curl_init($this->sources[$i]['url']);
- /**
- * Define options before add this handle
- */
- $ua = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36";
- curl_setopt($current, CURLOPT_RETURNTRANSFER , true);
- curl_setopt($current, CURLOPT_FOLLOWLOCATION, true);
- curl_setopt($current, CURLOPT_MAXREDIRS, 5);
- curl_setopt($current, CURLOPT_CONNECTTIMEOUT, 30);
- curl_setopt($current, CURLOPT_USERAGENT, $ua);
- /**
- *
- * @todo here comes the custom options of the user
- *
- */
- // TODO
- /**
- * Store the handle for future comparison
- */
- $this->sources[$i]['handle'] = $current;
- /**
- * Add a new handle to the cURL multi handle
- * It will be started instantly
- */
- curl_multi_add_handle($this->cMulti_handle, $current);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment