文章8
标签3
分类5

typecho 源码解析-路由

经过系统初始化、和插件之后,我们终于来到了路由工作的地方,几乎所有的 MVC 框架都不会缺少路由的功能,因为它提供了现代 web 开发必不可少的功能。路由就像桥梁一样,链接了 URL 和业务代码。

路由:根据 URL 将请求分配到对应的处理程序。

typecho的路由实现是使用正则匹配数据。路由数据保存在数据库,在系统初始化阶段通过 Widget_Init 取出路由表的数据,它看起来像这样:

Array
(
    [index] => Array
        (
            [url] => /
            [widget] => Widget_Archive
            [action] => render
            [regx] => |^[/]?$|
            [format] => /
            [params] => Array
                (
                )

        )

    [archive] => Array
        (
            [url] => /blog/
            [widget] => Widget_Archive
            [action] => render
            [regx] => |^/blog[/]?$|
            [format] => /blog/
            [params] => Array
                (
                )

        )

路由器类会使用子数组中的 regx 逐个匹配 pathinfo 中的路径,如果匹配成功,立即初始化并执行该类对应的 action 。以 index 为例,如果正则匹配成功,系统就会新建 Widget_Archive 类并执行 render 方法。

Typecho_Router::dispatch() 路由分发代码如下:

    public static function dispatch()
    {
        /** 获取PATHINFO */
        $pathInfo = self::getPathInfo();

        foreach (self::$_routingTable as $key => $route) {
            if (preg_match($route['regx'], $pathInfo, $matches)) {
                self::$current = $key;

                try {
                    /** 载入参数 */
                    $params = NULL;

                    if (!empty($route['params'])) {
                        unset($matches[0]);
                        $params = array_combine($route['params'], $matches);
                    }

                    $widget = Typecho_Widget::widget($route['widget'], NULL, $params);

                    if (isset($route['action'])) {
                        $widget->{$route['action']}();
                    }

                    return;

                } catch (Exception $e) {
                    if (404 == $e->getCode()) {
                        Typecho_Widget::destory($route['widget']);
                        continue;
                    }

                    throw $e;
                }
            }
        }

        /** 载入路由异常支持 */
        throw new Typecho_Router_Exception("Path '{$pathInfo}' not found", 404);
    }

如果匹配不成功,会通过 Typecho_Router_Exception 路由异常处理类抛出错误。

不知道你们会不会有把路由表写在数据表会不灵活的‘错觉’,第一次看到这里的代码的时候,我对于此,觉得特别不灵活,后来随着不断的阅读 typecho 的源码,发现作者提供了扩充路由表的方法。在 Helper 类的 addRouteremoveRoute 方法,有兴趣的同学可以去看下这两个方法。挺简单的。

匹配成功之后,如何执行业务逻辑和输出模版,我们下次再说。

    0 评论

    评论已关闭