PhalApiClient.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. <?php
  2. /**
  3. * PhalApi客户端SDK包(PHP版)
  4. *
  5. * - 以接口查询语言(ASQL)的方式来实现接口请求
  6. * - 出于简明客户端,将全部的类都归于同一个文件,避免过多的加载
  7. *
  8. * <br>使用示例:<br>
  9. ```
  10. * $rs = PhalApiClient::create()
  11. * ->withHost('http://demo.phalapi.net/')
  12. * ->withService('Default.Index')
  13. * ->withParams('name', 'dogstar')
  14. * ->withTimeout(3000)
  15. * ->request();
  16. *
  17. * var_dump($rs->getRet(), $rs->getData(), $rs->getMsg());
  18. ```
  19. *
  20. * @package PhalApi\SDK
  21. * @license http://www.phalapi.net/license GPL 协议
  22. * @link http://www.phalapi.net/
  23. * @author dogstar <chanzonghuang@gmail.com> 2015-10-16
  24. */
  25. class PhalApiClient {
  26. protected $host;
  27. protected $filter;
  28. protected $parser;
  29. protected $service;
  30. protected $timeoutMs;
  31. protected $params = array();
  32. /**
  33. * 创建一个接口实例,注意:不是单例模式
  34. * @return PhalApiClient
  35. */
  36. public static function create() {
  37. return new self();
  38. }
  39. protected function __construct() {
  40. $this->host = "";
  41. $this->parser = new PhalApiClientParserJson();
  42. }
  43. /**
  44. * 设置接口域名
  45. * @param string $host
  46. * @return PhalApiClient
  47. */
  48. public function withHost($host) {
  49. $this->host = $host;
  50. return $this;
  51. }
  52. /**
  53. * 设置过滤器,与服务器的DI()->filter对应
  54. * @param PhalApiClientFilter $filter 过滤器
  55. * @return PhalApiClient
  56. */
  57. public function withFilter(PhalApiClientFilter $filter) {
  58. $this->filter = $filter;
  59. return $this;
  60. }
  61. /**
  62. * 设置结果解析器,仅当不是JSON返回格式时才需要设置
  63. * @param PhalApiClientParser $parser 结果解析器
  64. * @return PhalApiClient
  65. */
  66. public function withParser(PhalApiClientParser $parser) {
  67. $this->parser = $parser;
  68. return $this;
  69. }
  70. /**
  71. * 重置,将接口服务名称、接口参数、请求超时进行重置,便于重复请求
  72. * @return PhalApiClient
  73. */
  74. public function reset() {
  75. $this->service = "";
  76. $this->timeoutMs = 3000;
  77. $this->params = array();
  78. return $this;
  79. }
  80. /**
  81. * 设置将在调用的接口服务名称,如:Default.Index
  82. * @param string $service 接口服务名称
  83. * @return PhalApiClient
  84. */
  85. public function withService($service) {
  86. $this->service = $service;
  87. return $this;
  88. }
  89. /**
  90. * 设置接口参数,此方法是唯一一个可以多次调用并累加参数的操作
  91. * @param string $name 参数名字
  92. * @param string $value 值
  93. * @return PhalApiClient
  94. */
  95. public function withParams($name, $value) {
  96. $this->params[$name] = $value;
  97. return $this;
  98. }
  99. /**
  100. * 设置超时时间,单位毫秒
  101. * @param int $timeoutMs 超时时间,单位毫秒
  102. * @return PhalApiClient
  103. */
  104. public function withTimeout($timeoutMs) {
  105. $this->timeoutMs = $timeoutMs;
  106. return $this;
  107. }
  108. /**
  109. * 发起接口请求
  110. * @return PhalApiClientResponse
  111. */
  112. public function request() {
  113. $url = $this->host;
  114. if (!empty($this->service)) {
  115. $url .= '?service=' . $this->service;
  116. }
  117. if ($this->filter !== null) {
  118. $this->filter->filter($this->service, $this->params);
  119. }
  120. $rs = $this->doRequest($url, $this->params, $this->timeoutMs);
  121. return $this->parser->parse($rs);
  122. }
  123. protected function doRequest($url, $data, $timeoutMs = 3000)
  124. {
  125. $ch = curl_init();
  126. curl_setopt($ch, CURLOPT_URL, $url);
  127. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  128. curl_setopt($ch, CURLOPT_HEADER, 0);
  129. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, $timeoutMs);
  130. if (!empty($data)) {
  131. curl_setopt($ch, CURLOPT_POST, 1);
  132. curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  133. }
  134. $rs = curl_exec($ch);
  135. curl_close($ch);
  136. return $rs;
  137. }
  138. }
  139. /**
  140. * 接口返回结果
  141. *
  142. * - 与接口返回的格式对应,即有:ret/data/msg
  143. */
  144. class PhalApiClientResponse {
  145. protected $ret = 200;
  146. protected $data = array();
  147. protected $msg = '';
  148. public function __construct($ret, $data = array(), $msg = '') {
  149. $this->ret = $ret;
  150. $this->data = $data;
  151. $this->msg = $msg;
  152. }
  153. public function getRet() {
  154. return $this->ret;
  155. }
  156. public function getData() {
  157. return $this->data;
  158. }
  159. public function getMsg() {
  160. return $this->msg;
  161. }
  162. }
  163. /**
  164. * 接口过滤器
  165. *
  166. * - 可用于接口签名生成
  167. */
  168. interface PhalApiClientFilter {
  169. /**
  170. * 过滤操作
  171. * @param string $service 接口服务名称
  172. * @param array $params 接口参数,注意是引用。可以直接修改
  173. * @return null
  174. */
  175. public function filter($service, array &$params);
  176. }
  177. /**
  178. * 接口结果解析器
  179. *
  180. * - 可用于不同接口返回格式的处理
  181. */
  182. interface PhalApiClientParser {
  183. /**
  184. * 结果解析
  185. * @param string $apiResult
  186. * @return PhalApiClientResponse
  187. */
  188. public function parse($apiResult);
  189. }
  190. /**
  191. * JSON解析
  192. */
  193. class PhalApiClientParserJson implements PhalApiClientParser {
  194. public function parse($apiResult) {
  195. if ($apiResult === false) {
  196. return new PhalApiClientResponse(408, array(), 'Request Timeout');
  197. }
  198. $arr = json_decode($apiResult, true);
  199. if ($arr === false || empty($arr)) {
  200. return new PhalApiClientResponse(500, array(), 'Internal Server Error');
  201. }
  202. return new PhalApiClientResponse($arr['ret'], $arr['data'], $arr['msg']);
  203. }
  204. }