HTTP.Class.php 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. <?php // vim:set ts=4 sw=4 et:
  2. namespace Mall\Framework\SearchClient\Transport;
  3. /**
  4. * This file is part of the ElasticSearch PHP client
  5. *
  6. * (c) Raymond Julin <raymond.julin@gmail.com>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11. if (!defined('CURLE_OPERATION_TIMEDOUT'))
  12. define('CURLE_OPERATION_TIMEDOUT', 28);
  13. class HTTP extends Base
  14. {
  15. /**
  16. * How long before timing out CURL call
  17. */
  18. private $timeout = 10;
  19. /**
  20. * curl handler which is needed for reusing existing http connection to the server
  21. * @var resource
  22. */
  23. protected $ch;
  24. public function __construct($host = 'localhost', $port = 9200, $timeout = null)
  25. {
  26. parent::__construct($host, $port);
  27. if (null !== $timeout) {
  28. $this->setTimeout($timeout);
  29. }
  30. $this->ch = curl_init();
  31. }
  32. /**
  33. * Index a new document or update it if existing
  34. *
  35. * @return array
  36. * @param array $document
  37. * @param mixed $id Optional
  38. * @param array $options
  39. */
  40. public function index($document, $id = false, array $options = array())
  41. {
  42. $url = $this->buildUrl(array($this->type, $id), $options);
  43. $method = ($id == false) ? "POST" : "PUT";
  44. return $this->call($url, $method, $document);
  45. }
  46. /**
  47. * Search
  48. *
  49. * @return array
  50. * @param array|string $query
  51. * @param array $options
  52. */
  53. public function search($query, array $options = array())
  54. {
  55. $result = false;
  56. if (is_array($query)) {
  57. /**
  58. * Array implies using the JSON query DSL
  59. */
  60. $arg = "_search";
  61. if (isset($options['routing'])) {
  62. $arg = "_search?routing=" . $options['routing'];
  63. }
  64. $url = $this->buildUrl(array(
  65. $this->type, $arg
  66. ));
  67. $result = $this->call($url, "GET", $query);
  68. } elseif (is_string($query)) {
  69. /**
  70. * String based search means http query string search
  71. */
  72. $url = $this->buildUrl(array(
  73. $this->type, "_search?q=" . $query
  74. ));
  75. $result = $this->call($url, "POST", $options);
  76. }
  77. return $result;
  78. }
  79. /**
  80. * ScrollSearch
  81. * @param $query
  82. * @param string $scroll
  83. * @param $size
  84. * @param array $options
  85. * @return array|bool
  86. * @throws HTTPException
  87. */
  88. public function scrollSearch($query, $scroll = '10s', $size = 2000, array $options = array())
  89. {
  90. $result = false;
  91. $arg = "_search?scroll=".$scroll.'&size='.$size;
  92. if (is_array($query)) {
  93. if (isset($options['routing'])) {
  94. $arg .= "&routing=" . $options['routing'];
  95. }
  96. $url = $this->buildUrl(array(
  97. $this->type, $arg
  98. ));
  99. $result = $this->call($url, "GET", $query);
  100. } elseif (is_string($query)) {
  101. /**
  102. * String based search means http query string search
  103. */
  104. $url = $this->buildUrl(array(
  105. $this->type, $arg."&q=" . $query
  106. ));
  107. $result = $this->call($url, "POST", $options);
  108. }
  109. return $result;
  110. }
  111. public function batchUpdateFieldVaule($data, $query)
  112. {
  113. $url = $this->buildUrl(array(
  114. $this->type, "_update_by_query"
  115. ));
  116. $field_str = "";
  117. $condition = "";
  118. foreach ($data as $field => $v) {
  119. if(!empty($field_str)) {
  120. $condition = ";";
  121. }
  122. $field_str .= $condition . "ctx._source.$field = params.$field";
  123. }
  124. $update = [
  125. 'script' => [
  126. 'lang' => "painless",
  127. 'inline' => $field_str,
  128. "params" => $data
  129. ]
  130. ];
  131. $result = $this->call($url, "POST", array_merge($query, $update));
  132. return $result;
  133. }
  134. /**
  135. * 增加站点索引Index
  136. *
  137. * @param $index
  138. * @param $mappings
  139. * @return array|bool
  140. * @throws HTTPException
  141. * @author feng
  142. */
  143. public function createBase($index, $mappings)
  144. {
  145. $result = false;
  146. if (is_string($index)) {
  147. $url = '/' . $index;
  148. $result = $this->call($url, 'PUT', $mappings);
  149. }
  150. return $result;
  151. }
  152. /**
  153. * 删除站点索引Index
  154. *
  155. * @param $index
  156. * @return array|bool
  157. * @throws HTTPException
  158. */
  159. public function deleteBase($index)
  160. {
  161. $result = false;
  162. if (is_string($index)) {
  163. $url = '/' . $index;
  164. $result = $this->call($url, 'DELETE');
  165. }
  166. return $result;
  167. }
  168. /**
  169. * Search
  170. *
  171. * @return array
  172. * @param mixed $query
  173. * @param array $options Parameters to pass to delete action
  174. */
  175. public function deleteByQuery($query, array $options = array())
  176. {
  177. $options += array(
  178. 'refresh' => true
  179. );
  180. if (is_array($query)) {
  181. /**
  182. * Array implies using the JSON query DSL
  183. */
  184. $url = $this->buildUrl(array($this->type, "_query"));
  185. $result = $this->call($url, "DELETE", $query);
  186. } elseif (is_string($query)) {
  187. /**
  188. * String based search means http query string search
  189. */
  190. $url = $this->buildUrl(array($this->type, "_query"), array('q' => $query));
  191. $result = $this->call($url, "DELETE");
  192. }
  193. if ($options['refresh']) {
  194. $this->request('_refresh', "POST");
  195. }
  196. return !isset($result['error']);
  197. }
  198. /**
  199. * Perform a request against the given path/method/payload combination
  200. * Example:
  201. * $es->request('/_status');
  202. *
  203. * @param string|array $path
  204. * @param string $method
  205. * @param array|bool $payload
  206. * @param bool $buildUrl
  207. * @return array
  208. */
  209. public function request($path, $method = "GET", $payload = false, $buildUrl = true)
  210. {
  211. $path = $buildUrl ? $this->buildUrl($path) : $path;
  212. return $this->call($path, $method, $payload);
  213. }
  214. /**
  215. * Flush this index/type combination
  216. *
  217. * @return array
  218. * @param mixed $id Id of document to delete
  219. * @param array $options Parameters to pass to delete action
  220. */
  221. public function delete($id = false, array $options = array())
  222. {
  223. if ($id)
  224. return $this->call($this->buildUrl(array($this->type, $id), $options), "DELETE");
  225. else
  226. return $this->request(false, "DELETE");
  227. }
  228. /**
  229. * Perform a http call against an url with an optional payload
  230. *
  231. * @return array
  232. * @param string $url
  233. * @param string $method (GET/POST/PUT/DELETE)
  234. * @param array|bool $payload The document/instructions to pass along
  235. * @throws HTTPException
  236. */
  237. protected function call($url, $method = "GET", $payload = null)
  238. {
  239. $conn = $this->ch;
  240. $protocol = "http";
  241. $requestURL = $protocol . "://" . $this->host . ':' . $this->port . $url;
  242. // 设置header需要发送的参数
  243. $header = ['Content-Type:application/json'];
  244. curl_setopt($conn, CURLOPT_HTTPHEADER , $header);
  245. curl_setopt($conn, CURLOPT_URL, $requestURL);
  246. curl_setopt($conn, CURLOPT_TIMEOUT, $this->timeout);
  247. curl_setopt($conn, CURLOPT_PORT, $this->port);
  248. curl_setopt($conn, CURLOPT_RETURNTRANSFER, 1);
  249. curl_setopt($conn, CURLOPT_CUSTOMREQUEST, strtoupper($method));
  250. curl_setopt($conn, CURLOPT_FORBID_REUSE, 0);
  251. if (is_array($payload) && count($payload) > 0)
  252. curl_setopt($conn, CURLOPT_POSTFIELDS, json_encode($payload));
  253. else
  254. curl_setopt($conn, CURLOPT_POSTFIELDS, $payload);
  255. $response = curl_exec($conn);
  256. if ($response !== false) {
  257. $data = json_decode($response, true);
  258. if (!$data) {
  259. $data = array('error' => $response, "code" => curl_getinfo($conn, CURLINFO_HTTP_CODE));
  260. }
  261. } else {
  262. /**
  263. * cUrl error code reference can be found here:
  264. * http://curl.haxx.se/libcurl/c/libcurl-errors.html
  265. */
  266. $errno = curl_errno($conn);
  267. switch ($errno) {
  268. case CURLE_UNSUPPORTED_PROTOCOL:
  269. $error = "Unsupported protocol [$protocol]";
  270. break;
  271. case CURLE_FAILED_INIT:
  272. $error = "Internal cUrl error?";
  273. break;
  274. case CURLE_URL_MALFORMAT:
  275. $error = "Malformed URL [$requestURL] -d " . json_encode($payload);
  276. break;
  277. case CURLE_COULDNT_RESOLVE_PROXY:
  278. $error = "Couldnt resolve proxy";
  279. break;
  280. case CURLE_COULDNT_RESOLVE_HOST:
  281. $error = "Couldnt resolve host";
  282. break;
  283. case CURLE_COULDNT_CONNECT:
  284. $error = "Couldnt connect to host [{$this->host}], ElasticSearch down?";
  285. break;
  286. case CURLE_OPERATION_TIMEDOUT:
  287. $error = "Operation timed out on [$requestURL]";
  288. break;
  289. default:
  290. $error = "Unknown error";
  291. if ($errno == 0)
  292. $error .= ". Non-cUrl error";
  293. break;
  294. }
  295. $exception = new HTTPException($error);
  296. $exception->payload = $payload;
  297. $exception->port = $this->port;
  298. $exception->protocol = $protocol;
  299. $exception->host = $this->host;
  300. $exception->method = $method;
  301. throw $exception;
  302. }
  303. return $data;
  304. }
  305. public function setTimeout($timeout)
  306. {
  307. $this->timeout = $timeout;
  308. }
  309. public function getTimeout()
  310. {
  311. return $this->timeout;
  312. }
  313. }