框架获取和处理的代码如下(index.php)
<?php /** * 统一访问入口 */ require_once dirname(__FILE__) . '/init.php'; define('DS','/'); //$pai = new \PhalApi\PhalApi(); $pai = new \App\Common\MyPhalApi(); $pai->response()->output();具体处理方法如下:
<?php namespace App\Common; use PhalApi\ApiFactory; use PhalApi\Exception; use PhalApi; class MyPhalApi extends \PhalApi\PhalApi { /** * 响应操作 * * 通过工厂方法创建合适的控制器,然后调用指定的方法,最后返回格式化的数据。 * * @return mixed 根据配置的或者手动设置的返回格式,将结果返回 * 其结果包含以下元素: ``` * array( * 'ret' => 200, //服务器响应状态 * 'data' => array(), //正常并成功响应后,返回给客户端的数据 * 'msg' => '', //错误提示信息 * ); ``` */ public function response() { $di = \PhalApi\DI(); error_reporting(E_ALL & ~E_NOTICE); set_error_handler(array(&$this,"customError")); // 开始响应接口请求 $di->tracer->mark('PHALAPI_RESPONSE'); $rs = $di->response; $isError = 0; $errorData = \PhalApi\DI()->requestInfo->get('errorData'); 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()); //$di->logger->error(\PhalApi\DI()->request->getService(), strval($ex)); if(!empty($errorData)){ $di->logger->error(\PhalApi\DI()->request->getService(),['errorData'=>$errorData]); } $di->logger->error(\PhalApi\DI()->request->getService(),['request'=>\PhalApi\DI()->request->getAll(),'header'=>\PhalApi\DI()->request->getAllHeaders()]); $di->logger->error(\PhalApi\DI()->request->getService(),['code'=>$ex->getCode(),'message'=>$ex->getMessage(),'exception'=>$ex->getTrace()]); $isError = 1; } catch (\Exception $ex) { // 不可控的异常 $di->logger->error(\PhalApi\DI()->request->getService(),['errorData'=>$errorData]); $di->logger->error(\PhalApi\DI()->request->getService(),['request'=>\PhalApi\DI()->request->getAll(),'header'=>\PhalApi\DI()->request->getAllHeaders()]); $di->logger->error(\PhalApi\DI()->request->getService(),['code'=>$ex->getCode(),'message'=>$ex->getMessage(),'exception'=>$ex->getTrace()]); $isError = 1; if ($di->debug) { $rs->setRet($ex->getCode()); $rs->setMsg($ex->getMessage()); $rs->setDebug('exception', $ex->getTrace()); } else { throw $ex; } }catch(\Error $er){ $isError = 1; //捕获错误 $di->logger->error(\PhalApi\DI()->request->getService(),['errorData'=>$errorData]); $di->logger->error(\PhalApi\DI()->request->getService(),['request'=>\PhalApi\DI()->request->getAll(),'header'=>\PhalApi\DI()->request->getAllHeaders()]); $di->logger->error(\PhalApi\DI()->request->getService(), strval($er)); } // 结束接口调度 $di->tracer->mark('PHALAPI_FINISH'); $rs->setDebug('stack', $di->tracer->getStack()); $rs->setDebug('sqls', $di->tracer->getSqls()); $rs->setDebug('version', PHALAPI_VERSION); if($isError){ $di->logger->error(\PhalApi\DI()->request->getService(), ['stack'=>$di->tracer->getStack(),'sqls'=>$di->tracer->getSqls()]); } return $rs; } }其他都是调试和日志以及异常处理方式,其实关键响应代码是这一句:
$data = call_user_func(array($api, $action)); $rs->setData($data);通过call_user_func来调用用户真正想要执行的类文件方法。现在大部分框架基本上是路由解析成功之后由call_user_func或者反射来调用方法执行.
当类方法运行结束后,通过return返回执行结果,就是这里的$data.这里request的相关操作就结束了,然后就要把运行的结果通过response响应给请求的用户.$rs是响应对象,这里setData就是把结果数据注入到响应类.
正面是响应类:
/** ------------------ 结果输出 ------------------ **/ /** * 结果输出 */ public function output() { $this->handleHeaders($this->headers); $rs = $this->getResult(); echo $this->formatResult($rs); }这里响应类主要做了以下操作:
1.添加响应头:
/** ------------------ 内部方法 ------------------ **/ protected function handleHeaders($headers) { header('Access-Control-Allow-Origin:*'); // *代表允许任何网址请求 header('Access-Control-Allow-Methods:POST,GET,OPTIONS,DELETE'); // 允许请求的类型 header('Access-Control-Allow-Headers: Content-Type,Content-Length,Accept-Encoding,X-Requested-with, Origin,token,sign,nonce,auth,app,deviceId,lang'); foreach ($headers as $key => $content) { @header($key . ': ' . $content); } }2.按相关数据格式组装结果数据
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; }3.输出数据,这里是一个抽象方法:
/** * 格式化需要输出返回的结果 * * @param array $result 待返回的结果数据 * * @see Response::getResult() */ abstract protected function formatResult($result);具体由子类实现,比如我想用户获取到的都是json格式:
public function __construct($options = 0) { $this->options = $options; $this->addHeaders('Content-Type', 'application/json;charset=utf-8'); } protected function formatResult($result) { return json_encode($result, $this->options); }这样组装成json数组再echo到用户。平常我们访问自己的php文件,比如
<?php echo '333';浏览器访问界面会打印出33.这里框架相当于在打印之前添加了一系列响应header头,然后把这个要输出的数据组装成想要的格式,最后echo到浏览器。本质是一样的。