老刘 Yii2 源码学习笔记之 Module 类

关系类图

从上图可以看出 Application 类继承了 Module,在框架中的是非常重要角色。

加载配置

public function setModules($modules)
    {
        foreach ($modules as $id => $module) {
            $this->_modules[$id] = $module;
        }
    }

baseModule 通过 setModules 把 Module 配置信息加载进来,赋值给 私有变量 _modules。

解析路由

Module 还有一个重要的功能,就是找到路由中的 Controller 位置:

public function createController($route)
    {
        if ($route === '') {
            $route = $this->defaultRoute;
        }

        // double slashes or leading/ending slashes may cause substr problem
        $route = trim($route, '/');
        if (strpos($route, '//') !== false) {
            return false;
        }

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

        // module and controller map take precedence
        if (isset($this->controllerMap[$id])) {
            $controller = Yii::createObject($this->controllerMap[$id], [$id, $this]);
            return [$controller, $route];
        }
        $module = $this->getModule($id);
        if ($module !== null) {
            return $module->createController($route);
        }

        if (($pos = strrpos($route, '/')) !== false) {
            $id .= '/' . substr($route, 0, $pos);
            $route = substr($route, $pos + 1);
        }

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

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

这个函数通过递归调用。假如路由是这样的:forum/admin/default/index

  1. 第一次递归会把路由字符串的 forum 过滤掉,还剩 admin/default/index
  2. 第二次 default/index
  3. 第三次 由于default不是Module, 通过Module的 init 方法知道当时的命名空间,所以就可以推断出Controller位置

总结

Module 的 getModule 方法 和 createController 方法 都是通过递归调用,层层剥离,设计精巧、简洁。

原文地址:https://www.cnblogs.com/liuzhang/p/10114787.html