1、入口文件
用户请求首先经过入口文件,通常是/public/index.php
,当然,你也可以更改或者增加新的入口文件。
通常入口文件的代码都比较简单,一个普通的入口文件代码如下:
<?php
/**
* 统一访问入口
*/
require_once dirname(__FILE__) . '/init.php';
$pai = new \PhalApi\PhalApi();
$pai->response()->output();
通常,不建议在应用入口文件中加入过多的代码,尤其是和业务逻辑相关的代码。
2、引导文件
入口文件内,加载框架引导文件/public/init.php
,会执行以下操作:
- 定义常量
- 引入composer
- 环境变量定义:时区设置
- 引入DI服务
- 设置是否调试模式
- 翻译语言包设定
您也可以在引导文件内定义自己使用的常量。
3、DI服务
DI依赖注入配置文件为/config/di.php
,根据配置注入系统运行过程中使用的类库。
此处也可以注入自己定义的类库,或者是重载DI服务内框架默认类库的方法等;
4、初始化PhalApi应用类
我们回到入口文件/public/index.php
,代码如下:
$pai = new \PhalApi\PhalApi();
$pai->response()->output();
初始化\PhalApi\PhalApi
类,执行其response()
方法,代码为:
public function response() {
$di = DI();
// 开始响应接口请求
$di->tracer->mark('PHALAPI_RESPONSE');
$rs = $di->response;
try {
// 接口调度与响应
$api = ApiFactory::generateService();
$action = $di->request->getServiceAction();
$data = call_user_func(array($api, $action));
$rs->setData($data);
} catch (Exception $ex) {
// 框架或项目可控的异常
$rs->setRet($ex->getCode());
$rs->setMsg($ex->getMessage());
} catch (\Exception $ex) {
// 不可控的异常
$di->logger->error(DI()->request->getService(), strval($ex));
if ($di->debug) {
$rs->setRet($ex->getCode());
$rs->setMsg($ex->getMessage());
$rs->setDebug('exception', $ex->getTrace());
} else {
throw $ex;
}
}
// 结束接口调度
$di->tracer->mark('PHALAPI_FINISH');
$rs->setDebug('stack', $di->tracer->getStack());
$rs->setDebug('sqls', $di->tracer->getSqls());
$rs->setDebug('version', PHALAPI_VERSION);
return $rs;
}
\PhalApi\PhalApi类的 response()
方法内会执行以下操作:
1、 全局跟踪器标记框架开始执行
2、 从DI服务内取response
响应服务
3、 执行方法ApiFactory::generateService();
应用初始化,返回实例化之后的接口服务类。
4、 【断点①】跟进ApiFactory::generateService();
方法内:调用DI服务内的request
服务来解析路由,解析成功后会分发请求并实例化接口服务类,然后执行接口服务基类的\PhalApi\Api->init()
方法(可以根据需要在子类重载)。
public function init() {
$this->createMemberValue();
$this->filterCheck();
$this->userCheck();
}
5、 跟进\PhalApi\Api->init()
方法内:
- 执行接口参数规则解析
createMemberValue()
(存为类成员变量); - 执行当前接口服务类的
filterCheck()
方法来调用DI服务内的filter
过滤器; - 执行当前接口服务类的
userCheck()
方法进行用户身份验证;
重点
从这里可以看到,在实例化接口服务类的过程中,依次顺序执行的方法为:
__construct()
构造函数init()
框架默认的初始化方法createMemberValue()
[必须]按参数规则解析生成接口参数filterCheck()
[可选]过滤器调用,如:签名验证userCheck()
[可选]用户身份验证
而这些方法都可以根据自己的业务逻辑,在接口服务类内重载。
6、回到【断点①】,$action = $di->request->getServiceAction();
,得到当前调用的接口服务方法(最小单元)。
7、调用当前接口服务$data = call_user_func(array($api, $action));
,返回数据;
8、设置返回数据、框架异常捕获、设置状态码、根据调试模式决定是否返回调试数据等;
9、在\PhalApi\PhalApi类的 response()
方法执行完毕之后,返回DI的response
服务。
10、此时,回到入口文件/public/index.php
。
5、结果输出
执行DI服务response
的DI->response->output()
方法,返回接口响应结果。
跟进DI->response->output()
方法,源码为:
public function output() {
// Step 1. 头部header处理
$this->handleHeaders($this->headers);
// Step 2. 获取数据结果
$rs = $this->getResult();
// Step 3. 结构体字段映射
$rs = $this->mapStructure($rs);
// Step 4. 序列化结果
$rs = $this->formatResult($rs);
// Step 5. 返回输出结果
$this->echoResult($rs);
}
版权属于:大卫科技Blog
本文链接:https://www.iyuu.cn/archives/414/
转载时须注明出处