_有句話說得好,最可怕的事情不是別人比你優秀,而是優秀的人竟然還比你更努力。 --《考拉小巫的留學成長日志》_
此篇章主要是講述接口統一請求的方式,以及提供一個PHP實現的簡單客戶端。
##1.13.1 指定接口服務:?service=XXX.XXX
我們統一固定用service參數來表示需要請求獲得的服務,并通過GET方式傳遞,即請求的URI格式為:
```
接口域名 + 入口路徑 + ?service=XXX.XXX
如:
http://dev.phalapi.com + /demo/ + ?service=User.GetBaseInfo
```
當我們在瀏覽器以GET方式請求時,可以在nignx看到這樣的日志:
```javascript
127.0.0.1 - - [07/Feb/2015:22:46:46 -0800] "GET /demo/?service=User.GetBaseInfo&sign=&user_id=1 HTTP/1.1" 200 107 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:11.0) Gecko/20100101 Firefox/11.0"
```
如果通過接口用POST方式請求,則會看到:
```javascript
127.0.0.1 - - [07/Feb/2015:19:32:05 -0800] "POST /demo/?service=User.GetBaseInfo&sign= HTTP/1.1" 200 135 "-" "-"
```
這里service的名稱,開頭不區分大小寫,建議統一以大寫開頭,以顯得專業。對應的接口是:
```javascript
class Api_User extends PhalApi_Api {
public function getBaseInfo() {
}
}
```
##1.13.2 統一參數用GET
在一個項目中,會有很多公共的接口參數,如客戶端、版本號、密鑰等。這些同樣可以納入GET參數里面,或者也可以放到POST里面。
> 溫馨提示:
> 這樣要求是有目的的,因為這樣的話可以在nginx的access日志里面查看來自客戶端的快照信息,以便統計或者定位問題。
##1.13.3 接口參數用POST
特別地,接口參數我們建議統一使用POST方式傳遞,理由很簡單:
+ 1、相對保護上傳的數據,一如密碼;
+ 2、避免特殊字符或者過大數據包在GET下的限制;
##1.13.4 測試下的模擬參數
默認地,PhalApi框架會將$_REQUEST作為接口參數的來源:
```javascript
DI()->request = 'PhalApi_Request';
```
當我們需要統一強制用$_GET,可以在init.php文件中這樣簡單定制:
```javascript
DI()->request = new PhalApi_Request($_GET);
```
同樣,也可以在init.php文件中強制用$_POST:
```javascript
DI()->request = new PhalApi_Request($_POST);
```
在測試環境下,為了模擬接口請求,我們需要人工提供接口參數,因此可以這樣輕松模擬:
```javascript
$str = 'service=User.GetBaseInfo&user_id=1';
parse_str($str, $params);
DI()->request = new PhalApi_Request($params);
```
##1.13.5 PHP接口客戶端示例
先看下調用和使用的代碼示例:
```javascript
<?php
require_once './PhalApiClient.php';
$config = array(
'host' => 'http://dev.phalapi.com/demo',
'secrect' => '******'
);
$client = new PhalApiClient($config);
$rs = $client->request('User.GetBaseInfo', array('userId' => 1));
if ($client->getRet() == PhalApiClient::RET_OK) {
var_dump($rs);
} else {
var_dump($client->getMsg());
var_dump($client->getUrl());
}
```
附調用接口的客戶端源代碼:
```javascript
//$ vim ./PhalApiClient.php
<?php
class PhalApiClient
{
protected $host;
protected $secrect = '';
protected $params = array();
protected $moreParams = array();
protected $url;
protected $ret;
protected $msg;
protected $data = array();
const RET_OK = 'OK';
const RET_WRONG = 'WRONG';
const RET_ERROR = 'ERROR';
public function __construct($config)
{
$this->host = rtrim($config['host'], '/') . '/';
$this->secrect = $config['secrect'];
}
public function request($service, $params = array(), $timeoutMs = 3000)
{
if (!empty($service)) {
$this->params['service'] = $service;
}
$this->params['sign'] = $this->encryptAppKey($params, $this->secrect);
$this->url = $this->host . '?' . http_build_query($this->params);
$this->moreParams = $params;
$rs = $this->doRequest($this->url, $params, $timeoutMs);
if ($rs === false) {
$this->ret = self::RET_ERROR;
$this->msg = '后臺接口請求超時';
return $this->getData();
}
$rs = json_decode($rs, true);
if (isset($rs['data']['code']) && $rs['data']['code'] != 0) {
$this->ret = self::RET_WRONG;
$this->msg = '接口調用失敗[code =' . $rs['data']['code'] . ']' . ', 錯誤>信息:' . isset($rs['data']['msg']) ? $rs['data']['msg'] : '無';
return $this->getData();
}
$this->ret = intval($rs['ret']) == 200 ? self::RET_OK : self::RET_WRONG;
$this->data = $rs['data'];
$this->msg = $rs['msg'];
return $this->getData();
}
public function getRet()
{
return $this->ret;
}
public function getData()
{
return $this->data;
}
public function getMsg()
{
return $this->msg;
}
public function getUrl()
{
return $this->url . '&' . http_build_query($this->moreParams);
}
protected function encryptAppKey($params, $secrect)
{
return '';
}
protected function doRequest($url, $data, $timeoutMs = 3000)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, $timeoutMs);
if (!empty($data)) {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
$rs = curl_exec($ch);
curl_close($ch);
return $rs;
}
}
```
- 歡迎使用PhalApi!
- 接口,從簡單開始!
- [1.1]-下載與安裝
- [1.2]-創建一個自己的項目
- [1.3]-在線體驗
- [1.4]-文檔、幫助和官網
- [1.10]-對PhalApi框架的抉擇
- [1.11]-快速入門(backup)
- [1.12]-參數規則:接口參數規則配置
- [1.13]-統一的接口請求方式:_sevice=XXX.XXX
- [1.14]-統一的返回格式和結構:ret-data-msg
- [1.15]-數據庫操作:基于NotORM的使用及優化
- [1.16]-配置讀取:內外網環境配置的完美切換
- [1.17]-日記紀錄:簡化版的日記接口
- [1.18]-快速函數:人性化的關懷
- [1.19]-DI服務速查:各資源服務一覽表
- [1.20]-DB操作:數據庫基本操作速查
- [1.21]-類的自動加載:遵循PEAR包的命名規范
- [1.22]-簽名驗證:自定義簽名規則
- [1.23]-請求和響應:GET和POST兩者皆可得及超越JSON格式返回
- [1.24]-緩存策略:更靈活地可配置化的多級緩存
- [1.25]-國際化翻譯:為走向國際化提前做好翻譯準備
- [1.26]-數據安全:數據對稱加密方案
- [1.27]-精益開發:更富表現力的Model層和重量級數據獲取的應對方案
- [1.28]-COOKIE:對COOKIE原生態的支持及記憶加密升級版
- [1.29]-開放與封閉:多入口和統一初始化
- [1.30]-保持的力量:接口開發最佳實踐
- [1.31]-新型計劃任務:以接口形式實現的計劃任務
- [2.11]-核心思想:DI依賴注入-讓資源更可控
- [2.12]-海量數據:可配置的分庫分表
- [2.13]-接口調試:在線SQL語句查看與性能優化
- [2.14]-測試驅動開發:意圖導向編程下的接口開發
- [2.15]-演進:新型計劃任務續篇
- [2.16]-領域驅動設計:應對復雜領域業務的Domain層
- [2.17]-微服務:Api接口服務層
- [2.18]-定制化:資源服務的再實現
- [2.19]-擴展庫:可重用的擴展類庫
- [2.20]-約定編程:架構明顯的編程風格
- [2.21]-服務器統一部署方案簡明版:CentOs---Nginx---php-fpm---MySql-[--Memcached]
- [2.22]-更多工具:精益項目和團隊建設
- [3.1]-擴展類庫:微信開發
- [3.2]-擴展類庫:代理模式下phprpc協議的輕松支持
- [3.3]-擴展類庫:基于PHPMailer的郵件發送
- [3.4]-擴展類庫:優酷開放平臺接口調用
- [3.5]-擴展類庫:七牛云存儲接口調用
- [3.6]-擴展類庫:新型計劃任務
- [3.8]-擴展類庫:用戶、會話和第三方登錄集成
- [3.9]-擴展類庫:swoole支持下的長鏈接和異步任務實現
- [3.11]-擴展類庫:基于FastRoute的快速路由
- [4.2]-開發實戰2:模擬優酷開放平臺接口項目開發
- [4.3]-開發實戰3:一個簡單的小型項目開發(奔跑吧兄弟投票活動)
- [5.1]-架構與思想:PhalApi核心設計和思想解讀
- [5.2]-雜談:扯一些PhalApi的前世和今生
- [5.3]-框架總結:術語表和PHP開發建議
- [5.4]-許可
- [5.5]-聯系和加入我們
- [5.6]-更新日記
- [5.8]-致框架貢獻者:加入PhalApi開源指南
- [6.1]-基于接口查詢語言的SDK包
- [6.2]-SDK包(JAVA版)
- [6.3]-SDK包(PHP版)
- [6.4]-SDK包(Objective-C版)
- [6.5]-SDK包(javascript版)
- [6.6]-SDK包(Ruby版)
- [8.1]-PhalApi視頻教程
- 附錄1:接口文檔參考模板