关系类图

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

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

加载配置

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

base\Module 通过 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 方法 都是通过递归调用,层层剥离,设计精巧、简洁。

05-02 07:22