PhalApi框架之生命周期分析-原创文章

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()方法进行用户身份验证;

重点
从这里可以看到,在实例化接口服务类的过程中,依次顺序执行的方法为:

  1. __construct()构造函数
  2. init()框架默认的初始化方法
  3. createMemberValue()[必须]按参数规则解析生成接口参数
  4. filterCheck()[可选]过滤器调用,如:签名验证
  5. 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服务responseDI->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);
}
最后修改:2020 年 11 月 19 日 02 : 54 PM
如果觉得我的文章对你有用,请随意赞赏

发表评论