1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace MultiHttp; |
4
|
|
|
|
5
|
|
|
use MultiHttp\Exception\InvalidArgumentException; |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* |
9
|
|
|
* @author [email protected] [email protected] |
10
|
|
|
* Date: 2017/6/9 |
11
|
|
|
* Time: 15:09 |
12
|
|
|
* @version $Id: $ |
13
|
|
|
* @since 1.0 |
14
|
|
|
* @copyright Sina Corp. |
15
|
|
|
*/ |
16
|
|
|
class MultiRequest |
17
|
|
|
{ |
18
|
|
|
/** |
19
|
|
|
* @var [Response] |
20
|
|
|
*/ |
21
|
1 |
|
protected static $requestPool; |
22
|
1 |
|
protected static $multiHandler; |
23
|
1 |
|
protected $defaultOptions = array(); |
24
|
|
|
private static $instance; |
25
|
|
|
protected static $loggerHandler; |
26
|
|
|
/** |
27
|
1 |
|
* MultiRequest constructor. |
28
|
1 |
|
*/ |
29
|
1 |
|
protected function __construct() |
30
|
|
|
{ |
31
|
1 |
|
} |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* @return MultiRequest |
35
|
|
|
*/ |
36
|
|
|
public static function create() |
37
|
|
|
{ |
38
|
|
|
if (!(self::$instance instanceof self)) { |
39
|
1 |
|
self::$instance = new self; |
40
|
1 |
|
} |
41
|
1 |
|
self::prepare(); |
42
|
1 |
|
return self::$instance; |
43
|
1 |
|
} |
44
|
|
|
|
45
|
1 |
|
/** |
46
|
|
|
* @param array $options |
47
|
1 |
|
* @return $this |
48
|
|
|
*/ |
49
|
|
|
public function setDefaults(array $options = array()){ |
50
|
1 |
|
$this->defaultOptions = $options; |
51
|
|
|
return $this; |
52
|
1 |
|
} |
53
|
1 |
|
protected static function prepare() |
54
|
1 |
|
{ |
55
|
1 |
|
self::$multiHandler = curl_multi_init(); |
56
|
1 |
|
} |
57
|
1 |
|
|
58
|
|
|
/** |
59
|
|
|
* @param $method |
60
|
1 |
|
* @param $uri |
61
|
1 |
|
* @param $payload |
62
|
|
|
* @param array $options |
63
|
1 |
|
* @return $this |
64
|
1 |
|
*/ |
65
|
1 |
View Code Duplication |
public function add($method, $uri, $payload, array $options = array()) |
|
|
|
|
66
|
|
|
{ |
67
|
|
|
$options = array( |
68
|
|
|
'method' => $method, |
69
|
|
|
'url' => $uri, |
70
|
|
|
'data' => $payload, |
71
|
1 |
|
) + $options; |
72
|
1 |
|
$this->addOptions(array($options)); |
73
|
|
|
return $this; |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* @param array $URLOptions |
78
|
|
|
* example: array(array('url'=>'http://localhost:9999/','timeout'=>1, 'method'=>'POST', 'data'=>'aa=bb&c=d')) |
79
|
|
|
* @return $this |
80
|
|
|
*/ |
81
|
|
|
public function addOptions(array $URLOptions) |
82
|
|
|
{ |
83
|
|
|
foreach ($URLOptions as $options) { |
84
|
|
|
$options = $options + $this->defaultOptions; |
85
|
|
|
$request = Request::create()->addOptions($options)->applyOptions(); |
86
|
|
|
if (isset($options['callback'])) { |
87
|
1 |
|
$request->onEnd($options['callback']); |
88
|
|
|
} |
89
|
|
|
$this->import($request); |
90
|
1 |
|
} |
91
|
1 |
|
return $this; |
92
|
|
|
} |
93
|
1 |
|
|
94
|
1 |
|
/** |
95
|
1 |
|
* @param Request $request |
96
|
1 |
|
* @return $this |
97
|
1 |
|
*/ |
98
|
1 |
|
public function import(Request $request) |
99
|
1 |
|
{ |
100
|
1 |
|
if (!is_resource($request->curlHandle)) { |
101
|
|
|
throw new InvalidArgumentException('Request curl handle is not initialized'); |
102
|
1 |
|
} |
103
|
1 |
|
curl_multi_add_handle(self::$multiHandler, $request->curlHandle); |
104
|
1 |
|
self::$requestPool[] = $request; |
105
|
|
|
return $this; |
106
|
1 |
|
} |
107
|
1 |
|
|
108
|
|
|
/** |
109
|
|
|
* @return array(Response) |
|
|
|
|
110
|
|
|
*/ |
111
|
|
|
public function execute() |
112
|
|
|
{ |
113
|
|
|
$sleepTime = 1000;//microsecond, prevent CPU 100% |
114
|
|
|
do { |
115
|
|
|
curl_multi_exec(self::$multiHandler, $active); |
116
|
|
|
// bug in PHP 5.3.18+ where curl_multi_select can return -1 |
117
|
|
|
// https://bugs.php.net/bug.php?id=63411 |
118
|
|
|
if (curl_multi_select(self::$multiHandler) == -1) { |
119
|
|
|
usleep($sleepTime); |
120
|
|
|
} |
121
|
|
|
usleep($sleepTime); |
122
|
|
|
} while ($active); |
123
|
|
|
$return = array(); |
124
|
|
|
foreach (self::$requestPool as $request) { |
125
|
|
|
$return[] = $request->send(true); |
126
|
|
|
curl_multi_remove_handle(self::$multiHandler, $request->curlHandle); |
127
|
|
|
curl_close($request->curlHandle); |
128
|
|
|
} |
129
|
|
|
curl_multi_close(self::$multiHandler); |
130
|
|
|
self::$requestPool = null; |
131
|
|
|
return $return; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
} |
135
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.