🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 接口响应与在线调试 对于接口响应,PhalApi默认使用了HTTP+JSON。通过HTTP/HTTPS协议进行通讯,返回的结果则使用JSON格式进行传递。正常情况下,当接口服务正常响应时,如前面的Hello World接口,可能看到以下这样的响应头部信息和返回内容。 ```html HTTP/1.1 200 OK Content-Type: application/json;charset=utf-8 ... ... {"ret":200,"data":{"title":"Hello World!"},"msg":""} ``` 而当接口项目抛出了未捕捉的异常,或者因PHP语法问题而出现Error时,则没有内容返回,并且得到一个500的响应状态码。类似如下: ``` HTTP/1.1 500 Internal Server Error ``` ## 响应结构 回顾一下默认接口服务返回的内容。类似如下: ```html { "ret": 200, "data": { "title": "Hello World!", "content": "PHPer您好,欢迎使用PhalApi!", "version": "2.0.0", "time": 1499477583 }, "msg": "" } ``` ret字段是返回状态码,200表示成功;data字段是项目提供的业务数据,由接口开发人员定义;msg是异常情况下的错误提示信息。下面分别说之。 ### 业务数据 data 业务数据data为接口和客户端主要沟通对接的数据部分,可以为任何类型,由接口开发人员定义定义。但为了更好地扩展、向后兼容,建议都使用可扩展的集合形式,而非原生类型。也就是说,应该返回一个数组,而不应返回整型、布尔值、字符串这些基本类型。 业务数据主要是在Api层返回,即对应接口类的方法的返回结果。如下面的默认接口服务```?s=Site.Index```的实现代码。 ```php <?php namespace App\Api; use PhalApi\Api; class Site extends Api { public function index() { return array( 'title' => 'Hello World!', 'content' => \PhalApi\T('Hi {name}, welcome to use PhalApi!', array('name' => $this->username)), 'version' => PHALAPI_VERSION, 'time' => $_SERVER['REQUEST_TIME'], ); } ``` 实际上,具体的业务数据需要一段复杂的处理,以满足特定业务场景下的需要。Api层需要与Domain层和Model层共同协作,完成指定的功能。这里暂且知道接口结果是在Api层返回,对应接口类成员方法返回的结果即可。 ### 返回状态码 ret 返回状态码ret,用于表示接口响应的情况。参照自HTTP的状态码,ret主要分为四大类:正常响应、重定向、非法请求、服务器错误。 分类|ret范围|基数|说明 ---|---|---|--- 正常响应|200~299|200|表示接口服务正常响应 重定向|300~399|300|表示重定向,对应异常类[RedirectException](https://github.com/phalapi/kernal/blob/master/src/Exception/RedirectException.php)的异常码 非法请求|400~499|400|表示客户端请求非法,对应异常类[BadRequestException](https://github.com/phalapi/kernal/blob/master/src/Exception/BadRequestException.php)的异常码 服务器错误|500~599|500|表示服务器内容错误,对应异常类[InternalServerErrorException](https://github.com/phalapi/kernal/blob/master/src/Exception/InternalServerErrorException.php)的异常码 正常响应时,通常返回ret = 200,并且同时返回data部分的业务数据,以便客户端能实现所需要的业务功能。 值得注意的是,抛出的异常应该继承于[PhalApi\Exception](https://github.com/phalapi/kernal/blob/master/src/Exception.php)类,并且构造函数的第一个参数,是返回给客户端的错误提示信息,对应下面将讲到的msg字段。第二个参数是返回状态码的**叠加值**,也就是说最终的ret状态码都会在400的基数上加上这个叠加值,即:401 = 400 + 1。 例如,常见地,当签名失败时可以返回一个401错误,并提示“签名失败”。 ```php <?php namespace App\Api; use PhalApi\Api; use PhalApi\Exception\BadRequestException; class Hello extends Api { public function fail() { throw new BadRequestException('签名失败', 1); } } ``` 会得到以下结果输出: ``` { "ret": 401, "data": [], "msg": "Bad Request: 签名失败" } ``` ### 错误提示信息 msg 当接口不是正常响应,即ret不在2XX系列内时,msg字段会返回相应的错误提示信息。即当有异常触发时,会自动将异常的错误信息作为错误信息msg返回。 ## 扩展:如何使用其他返回格式? 除了使用JSON格式返回外,还可以使用其他格式返回结果。 例如在部分H5混合应用页面进行异步请求的情况下,客户端需要服务端返回JSONP格式的结果,则可以这样在DI配置文件./config/di.php中去掉以下注释。 ```php // 支持JsonP的返回 if (!empty($_GET['callback'])) { $di->response = new \PhalApi\Response\JsonpResponse($_GET['callback']); } ``` 目前,PhalApi 2.x 已经支持的响应格式有: 响应格式|实现类 ---|--- JSON格式|[PhalApi\Response\JsonResponse](https://github.com/phalapi/kernal/blob/master/src/Response/JsonResponse.php) JSONP格式|[PhalApi\Response\JsonResponse](https://github.com/phalapi/kernal/blob/master/src/Response/JsonResponse.php) XML格式|[PhalApi\Response\JsonResponse](https://github.com/phalapi/kernal/blob/master/src/Response/JsonResponse.php) 控制台格式|[PhalApi\Response\JsonResponse](https://github.com/phalapi/kernal/blob/master/src/Response/JsonResponse.php) 当需要返回一种当前PhalApi没提供的格式,需要返回其他格式时,可以: + 1、实现抽象方法[PhalApi\Response::formatResult($result)](https://github.com/phalapi/kernal/blob/master/src/Response.php)并返回格式化后结果 + 2、在./config/di.php文件中重新注册```\PhalApi\DI()->response```服务 ## 在线调试 ### 开启调试调试 开启调试模式很简单,主要有两种方式: + **单次请求开启调试**:默认添加请求参数```&__debug__=1``` + **全部请求开启调试**:把配置文件```./Config/sys.php```文件中的配置改成```'debug' => true,``` ### 调试信息有哪些? 正常响应的情况下,当开启调试模式后,会返回多一个```debug```字段,里面有相关的调试信息。如下所示: ``` { "ret": 200, "data": { }, "msg": "", "debug": { "stack": [ // 自定义埋点信息 ], "sqls": [ // 全部执行的SQL语句 ] } } ``` > 温馨提示:调试信息仅当在开启调试模式后,才会返回并显示。 在发生未能捕捉的异常时,并且开启调试模式后,会将发生的异常转换为对应的结果按结果格式返回,即其结构会变成以下这样: ``` { "ret": 0, // 异常时的错误码 "data": [], "msg": "", // 异常时的错误信息 "debug": { "exception": [ // 异常时的详细堆栈信息 ], "stack": [ // 自定义埋点信息 ], "sqls": [ // 全部执行的SQL语句 ] } } ``` + **查看全部执行的SQL语句** debug.sqls中会显示所执行的全部SQL语句,由框架自动搜集并统计。最后显示的信息格式是: ``` [序号 - 当前SQL的执行时间ms]所执行的SQL语句及参数列表 ``` 示例: ``` [1 - 0.32ms]SELECT * FROM tbl_user WHERE (id = ?); -- 1 ``` 表示是第一条执行的SQL语句,消耗了0.32毫秒,SQL语句是```SELECT * FROM tbl_user WHERE (id = ?);```,其中参数是1。 + **查看自定义埋点信息** debug.stack中埋点信息的格式如下: ``` [#序号 - 距离最初节点的执行时间ms - 节点标识]代码文件路径(文件行号) ``` 示例: ``` [#0 - 0ms]/path/to/phalapi/public/index.php(6) ``` 表示,这是第一个埋点(由框架自行添加),执行时间为0毫秒,所在位置是文件```/path/to/phalapi/public/index.php```的第6行。即第一条的埋点发生在框架初始化时。 与SQL语句的调试信息不同的是,自定义埋点则需要开发人员根据需要自行纪录,可以使用全球追踪器```PhalApi\DI()->tracer```进行纪录,其使用如下: ```php // 添加纪录埋点 PhalApi\DI()->tracer->mark(); // 添加纪录埋点,并指定节点标识 PhalApi\DI()->tracer->mark('DO_SOMETHING'); ``` 通过上面方法,可以对执行经过的路径作标记。你可以指定节点标识,也可以不指定。对一些复杂的接口,可以在业务代码中添加这样的埋点,追踪接口的响应时间,以便进一步优化性能。当然,更专业的性能分析工具推荐使用XHprof。 > 参考:用于性能分析的[XHprof扩展类库](http://git.oschina.net/dogstar/PhalApi-Library/tree/master/Xhprof)。 + **查看异常堆栈信息** 当有未能捕捉的接口异常时,开启调试模式后,框架会把对应的异常转换成对应的返回结果,并在debug.exception中体现。而不是像正常情况直接500,页面空白。这些都是由框架自动处理的。 例如,让我们故意制造一些麻烦,手动抛出一个异常。 ```php class Hello extends Api { public function fail() { throw new Exception('这是一个演示异常调试的示例', 501); } } ``` 再次请求后,除了SQL语句和自定义埋点信息外,还会看到这样的异常堆栈信息。然后便可根据返回的异常信息进行排查定位问题。 + **添加自定义调试信息** 当需要添加其他调试信息时,可以使用```PhalApi\DI()->response->setDebug()```进行添加。 如: ```php class Hello extends Api { public function fail() { $x = 'this is x'; $y = array('this is y'); \PhalApi\DI()->response->setDebug('x', $x); \PhalApi\DI()->response->setDebug('y', $y); } } ``` 请求后,可以看到: ``` "debug": { "x": "this is x", "y": [ "this is y" ] } ```