Api接口层称为接口服务层,负责对客户端的请求进行响应,处理接收客户端传递的参数,进行高层决策并对领域业务层进行调度,最后将处理结果返回给客户端。
接口参数,对于接口服务本身来说,是非常重要的。对于外部调用的客户端来说,同等重要。对于接口参数,我们希望能够既减轻后台开发对接口参数获取、判断、验证、文档编写的痛苦;又能方便客户端快速调用,明确参数的意义。由此,我们引入了参数规则这一概念,即:通过配置参数的规则,自动实现对参数的获取和验证,同时自动生成在线接口文档。
假设我们现在需要提供一个用户登录的接口,接口参数有用户名和密码,那么新增的接口类和规则如下:
// 文件 ./src/app/Api/User.php
namespace App\Api;
use PhalApi\Api;
class User extends Api {
public function getRules() {
return array(
'login' => array(
'username' => array('name' => 'username'),
'password' => array('name' => 'password'),
),
);
}
public function login() {
return array('username' => $this->username, 'password' => $this->password);
}
}
当请求此接口服务,并类似这样带上username和password参数时:
/?s=User.Login&username=dogstar&password=123456
就可以得到这样的返回结果。
{"ret":0,"data":{"username":"dogstar","password":"123456"},"msg":""}
回顾一下,在PhalApi中,掊口返回的结果的结构为:
{
"ret": 200, // 状态码
"data": {
// 业务数据
},
"msg": "" // 错误提示信息
}
正常情况下,在Api层返回的数据结果,会在返回结果的data字段中体现。例如:
class Hello extends Api {
public function world() {
return array('title' => 'Hello World!');
}
}
对应:
{
"ret": 200,
"data": {
"title": "Hello World!"
},
"msg": ""
}
成功返回时,状态码ret为200,并且错误信息msg为空。
对于异常情况,包括系统错误或者应用层的错误,可以通过抛出PhalApi\Exception系列的异常,中断请求并返回相关的错误信息。例如:
class Hello extends Api {
public function fail() {
throw new BadRequestException('签名失败', 1);
}
}
会得到以下结果输出:
{
"ret": 401,
"data": [],
"msg": "Bad Request: 签名失败"
}
如果需要支持JSONP返回格式,可以将 ./config/di.php
中的以下代码注释去掉:
// 支持JsonP的返回
if (!empty($_GET['callback'])) {
$di->response = new \PhalApi\Response\JsonpResponse($_GET['callback']);
}
然后在请求时,传入回调函数的名称callback,即可返回JSONP格式。例如请求:
http://dev.phalapi.net/?s=Hello.World&callback=test
返回:
test({"ret":200,"data":{"title":"Hello World!"},"msg":""})
如果需要返回XML格式,需要将\PhalApi\DI()->response
切换到XML响应类,如:
$di->response = new \PhalApi\Response\XmlResponse();
然后,可看到请求的接口返回类似如下:
常用的返回格式有如上的JSON、JSONP、XML返回格式。如果需要返回其他的格式,你可以:
如果希望能由客户端指定返回格式,可通过参数来动态切换。
对于默认返回的字段结构,源代码实现在PhalApi\Response::getResult()方法。相关代码片段如下:
abstract class Response {
public function getResult() {
$rs = array(
'ret' => $this->ret,
'data' => is_array($this->data) && empty($this->data) ? (object)$this->data : $this->data, // # 67 优化
'msg' => $this->msg,
);
if (!empty($this->debug)) {
$rs['debug'] = $this->debug;
}
return $rs;
}
}
如果需要修改默认的ret/data/msg,可以重载此方法,然后进行修改。值得注意的是,你可以基于现有的具体响应类进行继承重载。例如针对JSON的返回格式,先添加一个自己的扩展子类。例如只返回data部分:
// 新建 ./src/app/Common/MyResponse.php 文件
namespace App\Common;
use PhalApi\Response\JsonResponse ;
class MyResponse extends JsonResponse {
public function getResult() {
// 只返回data部分
$rs = parent::getResult();
return $rs['data'];
}
}
接着在 ./config/di.php 文件中重新注册$di->response
服务为此新的响应类实例。例如:
$di->response = new \App\Common\MyResponse();
完成子类重载,以及response服务重新注册后,再次访问接口,就会看到返回的结果去掉了ret和msg部分。
例如,对于Hello World接口服务,原来返回是:
{"ret":200,"data":{"title":"Hello World!"},"msg":""}
现在,返回是(只返回data部分):
{"title":"Hello World!"}