yii框架路由解析(二)

继上篇yii框架路由解析(一)拿到调用接口后,接着看yii框架是如何处理的。还是从handlerRequest()方法看起:

public function handleRequest($request)
{
        list($route, $params) = $request->resolve();
      
        $this->requestedRoute = $route;
        $result = $this->runAction($route, $params);
            
        return $result;
}

掐头去尾以及省去中间部分代码后,方法体就剩下以上这些。现在$route的值为api/test$params值为空,很明显,是通过runAction()方法对其进行处理并返回最终结果的。

public function runAction($route, $params = [])
{
        $parts = $this->createController($route);
        list($controller, $actionID) = $parts;
        $oldController = Yii::$app->controller;
        Yii::$app->controller = $controller;
        $result = $controller->runAction($actionID, $params);
        if ($oldController !== null) {
            Yii::$app->controller = $oldController;
        }

        return $result;
}

在方法一开始就调用了另一个方法createController()

public function createController($route)
{
        if (strpos($route, '/') !== false) {
            list($id, $route) = explode('/', $route, 2);
        } else {
            $id = $route;
            $route = '';
        }

        ...

        $controller = $this->createControllerByID($id);
        if ($controller === null && $route !== '') {
            $controller = $this->createControllerByID($id . '/' . $route);
            $route = '';
        }

        return $controller === null ? false : [$controller, $route];
}

这里还是省略了方法体中的一部分,该方法前面一部分是将传入的参数$route分为两部分,api赋值给$idtest赋值给$route,最终通过createControllerByID()方法找到在api路径下定义的所有接口,然后在给出的所有接口中找出当前调用的接口。最主要的是该方法生成了ApiController类对象,并赋值给$controller返回到上一层。回到上一层runAction()方法后,将当前调用接口名test赋值给$actionID,并作为参数,调用\yii\base\controller类中的runAction()方法。

public function runAction($id, $params = [])
{
        $action = $this->createAction($id);

        $result = null;
        if ($this->beforeAction($action)) {
            // run the action
            $result = $action->runWithParams($params);

            $result = $this->afterAction($action, $result);
            foreach ($modules as $module) {
                $result = $module->afterAction($action, $result);
            }
        }

        return $result;
}

在该方法一开始调用createAction()方法以接口名作为参数生成了对应的接口类对象:

public function createAction($id)
{
        $actionMap = $this->actions();
        if (isset($actionMap[$id])) {
            return Yii::createObject($actionMap[$id], [$id, $this]);
        } elseif (preg_match('/^[a-z0-9\\-_]+$/', $id) && strpos($id, '--') === false && trim($id, '-') === $id) {
            $methodName = 'action' . str_replace(' ', '', ucwords(implode(' ', explode('-', $id))));
            if (method_exists($this, $methodName)) {
                $method = new \ReflectionMethod($this, $methodName);
                if ($method->isPublic() && $method->getName() === $methodName) {
                    return new InlineAction($id, $this, $methodName);
                }
            }
        }

        return null;
}

在该方法中调用了ApiController中定义的actions()方法,该方法获取到的就是每个接口在项目中存储路径,以接口名作为数组的键,这样就可以通过接口名直接找到接口所在路径了。并通过createObject()方法生成TestAction对象,这里目前只需知道yii框架是通过createObject()方法根据接口名生成对应类对象即可,本章暂时不对该方法详细介绍。生成接口名对应类对象后,开始调用\yii\base\action中的runWithParams()方法对其进行处理,这里之所以能够调用是因为定义的每个接口都继承了类Action

use app\components\BaseAction;
class TestAction extends BaseAction
{
}

use yii\base\Action;
class BaseAction extends Action
{
}

再回到调用的runWithParams()方法中来:

//主要代码如下,省略一部分
public function runWithParams($params)
{
        $args = $this->controller->bindActionParams($this, $params);
     
        $result = call_user_func_array([$this, 'run'], $args);
    
        return $result;
}

这里面的$this->controller是什么东西呢?就是之前在调用createController方法时生成的ApiController类对象,是在构造函数中赋过去的。最终通过回调函数call_user_func_array()执行该接口对应的方法了,此时如果打印$result的值,就可以看到接口的返回值了。

另外,看这个回调函数的参数调用的run()方法,而在接口中是没有定义这个方法的,这是因为在接口继承的父类BaseAction中实现了该方法。

public function run()
{
        $handler = Yii::$app->controller->id;
        $this->$handler();
}

这里的id值也就是api了,所以要在每个接口中定义api()方法供调用了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值