_有句话说得好,最可怕的事情不是别人比你优秀,而是优秀的人竟然还比你更努力。 --《考拉小巫的留学成长日志》_
此篇章主要是讲述接口统一请求的方式,以及提供一个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:接口文档参考模板