• typecho流程原理和插件机制浅析(第一弹)


    •  5 推荐
    •  24 收藏,3.5k 浏览

    虽然新版本0.9在多次跳票后终于发布了,在漫长的等待里始终有一批人不离不弃,其中不乏一些主题和插件开发者,还有一些忠实的粉丝,但是就是这样一个blog系统还是由于缺乏相关文档和主题插件使很多想要摆脱wp的用户难以跨出最后一步,很多想要学习插件开发的人也因为对机制不了解找不到头绪,今天就简单介绍一下typecho的执行流程和插件机制,并配合一些简单的例子来帮助那些找不到头绪的人,大牛可以路过了!

    简要流程分析

    Typecho是单入口程序,一切访问都通过index.php,所以还要从index.php的代码开始。(以0.9正式版为例,代码只贴流程必须部分)

    if (!@include_once 'config.inc.php') {
        file_exists('./install.php') ? header('Location: install.php') : print('Missing Config File');
        exit;
    }
    
    /** 初始化组件 */
    Typecho_Widget::widget('Widget_Init');
    
    /** 注册一个初始化插件 */
    Typecho_Plugin::factory('index.php')->begin();
    
    /** 开始路由分发 */
    Typecho_Router::dispatch();
    
    /** 注册一个结束插件 */
    Typecho_Plugin::factory('index.php')->end();
    

    整个index.php只做了三件事

    • 加载config.inc.php(config.inc.php设置了相关目录、包含路径、加载系统基础类库、 程序初始化Typecho_Common::init();、最后设置数据库连接参数,此处自行查看)
    • 执行Typecho_Widget::widget('Widget_Init');
    • 执行Typecho_Router::dispatch();

    那么程序初始化又做了些什么呢?

            function __autoLoad($className)
            {
                /**
                 * 自动载入函数并不判断此类的文件是否存在, 我们认为当你显式的调用它时, 你已经确认它存在了
                 * 如果真的无法被加载, 那么系统将出现一个严重错误(Fetal Error)
                 * 如果你需要判断一个类能否被加载, 请使用 Typecho_Common::isAvailableClass 方法
                 */
                @include_once str_replace('_', '/', $className) . '.php';
            }
    

    设置自动载入,将Typecho_Widget_替换为/,并加上.php

    Typecho/Widget.php,并include_once 'Typecho/Widget.php';

    执行Typecho_Widght类的Widget静态函数,参数为Widget_Init

        public static function widget($alias, $params = NULL, $request = NULL, $enableResponse = true)
        {
            list($className) = explode('@', $alias);
    
            if (!isset(self::$_widgetPool[$alias])) {
                $fileName = str_replace('_', '/', $className) . '.php';
                require_once $fileName;
    
                /** 如果类不存在 */
                if (!class_exists($className)) {
                    /** Typecho_Exception */
                    require_once 'Typecho/Widget/Exception.php';
                    throw new Typecho_Widget_Exception($className);
                }
    
                /** 初始化request */
                if (!empty($request)) {
                    $requestObject = new Typecho_Request();
                    $requestObject->setParams($request);
                } else {
                    $requestObject = Typecho_Request::getInstance();
                }
    
                /** 初始化response */
                $responseObject = $enableResponse ? Typecho_Response::getInstance()
                : Typecho_Widget_Helper_Empty::getInstance();
    
                /** 初始化组件 */
                $widget = new $className($requestObject, $responseObject, $params);
    
                $widget->execute();
                self::$_widgetPool[$alias] = $widget;
            }
    
            return self::$_widgetPool[$alias];
        }
    

    同样,将Widget_Init_替换为/,并加上.php

    Widget/Init.php,并require_once 'Widget/Init.php';

    并且执行Widget_Initexecute函数

    <?php
    /**
     * Typecho Blog Platform
     *
     * @copyright  Copyright (c) 2008 Typecho team (http://www.typecho.org)
     * @license    GNU General Public License 2.0
     * @version    $Id$
     */
    
    /**
     * 初始化模块
     *
     * @package Widget
     */
    class Widget_Init extends Typecho_Widget
    {
        /**
         * 入口函数,初始化路由器
         *
         * @access public
         * @return void
         */
        public function execute()
        {
            /** 对变量赋值 */
            $options = $this->widget('Widget_Options'); 
    
            /** cookie初始化 */
            Typecho_Cookie::setPrefix($options->siteUrl);
    
            /** 初始化charset */
            Typecho_Common::$charset = $options->charset;
    
            /** 初始化exception */
            Typecho_Common::$exceptionHandle = 'Widget_ExceptionHandle';
    
            /** 设置路径 */
            if (defined('__TYPECHO_PATHINFO_ENCODING__')) {
                $pathInfo = $this->request->getPathInfo(__TYPECHO_PATHINFO_ENCODING__, $options->charset);
            } else {
                $pathInfo = $this->request->getPathInfo();
            }
    
            Typecho_Router::setPathInfo($pathInfo);
    
            /** 初始化路由器 */
            Typecho_Router::setRoutes($options->routingTable);
    
            /** 初始化插件 */
            Typecho_Plugin::init($options->plugins);
    
            /** 初始化回执 */
            $this->response->setCharset($options->charset);
            $this->response->setContentType($options->contentType);
    
            /** 默认时区 */
            if (function_exists("ini_get") && !ini_get("date.timezone") && function_exists("date_default_timezone_set")) {
                @date_default_timezone_set('UTC');
            }
    
            /** 初始化时区 */
            Typecho_Date::setTimezoneOffset($options->timezone);
    
            /** 开始会话, 减小负载只针对后台打开session支持 */
            if ($this->widget('Widget_User')->hasLogin()) {
                @session_start();
            }
    
            /** 监听缓冲区 */
            ob_start();
        }
    }
    

    真正的初始化是在Typecho_Init,其中最重要的两项任务就是

    • 获取 pathinfo (比如访问文章http://localhost/archives/1/,则 pathinfo 为/archives/1/
    • 从数据库读取系统路由表(optionroutingTable字段)

    举例系统安装完成默认路由

                [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
                            (
                            )
    
                    )
    
                [do] => Array
                    (
                        [url] => /action/[action:alpha]
                        [widget] => Widget_Do
                        [action] => action
                        [regx] => |^/action/([_0-9a-zA-Z-]+)[/]?$|
                        [format] => /action/%s
                        [params] => Array
                            (
                                [0] => action
                            )
    
                    )
    
                [post] => Array
                    (
                        [url] => /archives/[cid:digital]/
                        [widget] => Widget_Archive
                        [action] => render
                        [regx] => |^/archives/([0-9]+)[/]?$|
                        [format] => /archives/%s/
                        [params] => Array
                            (
                                [0] => cid
                            )
    
                    )
    
                [attachment] => Array
                    (
                        [url] => /attachment/[cid:digital]/
                        [widget] => Widget_Archive
                        [action] => render
                        [regx] => |^/attachment/([0-9]+)[/]?$|
                        [format] => /attachment/%s/
                        [params] => Array
                            (
                                [0] => cid
                            )
    
                    )
    
                [category] => Array
                    (
                        [url] => /category/[slug]/
                        [widget] => Widget_Archive
                        [action] => render
                        [regx] => |^/category/([^/]+)[/]?$|
                        [format] => /category/%s/
                        [params] => Array
                            (
                                [0] => slug
                            )
    
                    )
    
                [tag] => Array
                    (
                        [url] => /tag/[slug]/
                        [widget] => Widget_Archive
                        [action] => render
                        [regx] => |^/tag/([^/]+)[/]?$|
                        [format] => /tag/%s/
                        [params] => Array
                            (
                                [0] => slug
                            )
    
                    )
    
                [author] => Array
                    (
                        [url] => /author/[uid:digital]/
                        [widget] => Widget_Archive
                        [action] => render
                        [regx] => |^/author/([0-9]+)[/]?$|
                        [format] => /author/%s/
                        [params] => Array
                            (
                                [0] => uid
                            )
    
                    )
    
                [search] => Array
                    (
                        [url] => /search/[keywords]/
                        [widget] => Widget_Archive
                        [action] => render
                        [regx] => |^/search/([^/]+)[/]?$|
                        [format] => /search/%s/
                        [params] => Array
                            (
                                [0] => keywords
                            )
    
                    )
    
                [index_page] => Array
                    (
                        [url] => /page/[page:digital]/
                        [widget] => Widget_Archive
                        [action] => render
                        [regx] => |^/page/([0-9]+)[/]?$|
                        [format] => /page/%s/
                        [params] => Array
                            (
                                [0] => page
                            )
    
                    )
    
                [archive_page] => Array
                    (
                        [url] => /blog/page/[page:digital]/
                        [widget] => Widget_Archive
                        [action] => render
                        [regx] => |^/blog/page/([0-9]+)[/]?$|
                        [format] => /blog/page/%s/
                        [params] => Array
                            (
                                [0] => page
                            )
    
                    )
    
                [category_page] => Array
                    (
                        [url] => /category/[slug]/[page:digital]/
                        [widget] => Widget_Archive
                        [action] => render
                        [regx] => |^/category/([^/]+)/([0-9]+)[/]?$|
                        [format] => /category/%s/%s/
                        [params] => Array
                            (
                                [0] => slug
                                [1] => page
                            )
    
                    )
    
                [tag_page] => Array
                    (
                        [url] => /tag/[slug]/[page:digital]/
                        [widget] => Widget_Archive
                        [action] => render
                        [regx] => |^/tag/([^/]+)/([0-9]+)[/]?$|
                        [format] => /tag/%s/%s/
                        [params] => Array
                            (
                                [0] => slug
                                [1] => page
                            )
    
                    )
    
                [author_page] => Array
                    (
                        [url] => /author/[uid:digital]/[page:digital]/
                        [widget] => Widget_Archive
                        [action] => render
                        [regx] => |^/author/([0-9]+)/([0-9]+)[/]?$|
                        [format] => /author/%s/%s/
                        [params] => Array
                            (
                                [0] => uid
                                [1] => page
                            )
    
                    )
    
                [search_page] => Array
                    (
                        [url] => /search/[keywords]/[page:digital]/
                        [widget] => Widget_Archive
                        [action] => render
                        [regx] => |^/search/([^/]+)/([0-9]+)[/]?$|
                        [format] => /search/%s/%s/
                        [params] => Array
                            (
                                [0] => keywords
                                [1] => page
                            )
    
                    )
    
                [archive_year] => Array
                    (
                        [url] => /[year:digital:4]/
                        [widget] => Widget_Archive
                        [action] => render
                        [regx] => |^/([0-9]{4})[/]?$|
                        [format] => /%s/
                        [params] => Array
                            (
                                [0] => year
                            )
    
                    )
    
                [archive_month] => Array
                    (
                        [url] => /[year:digital:4]/[month:digital:2]/
                        [widget] => Widget_Archive
                        [action] => render
                        [regx] => |^/([0-9]{4})/([0-9]{2})[/]?$|
                        [format] => /%s/%s/
                        [params] => Array
                            (
                                [0] => year
                                [1] => month
                            )
    
                    )
    
                [archive_day] => Array
                    (
                        [url] => /[year:digital:4]/[month:digital:2]/[day:digital:2]/
                        [widget] => Widget_Archive
                        [action] => render
                        [regx] => |^/([0-9]{4})/([0-9]{2})/([0-9]{2})[/]?$|
                        [format] => /%s/%s/%s/
                        [params] => Array
                            (
                                [0] => year
                                [1] => month
                                [2] => day
                            )
    
                    )
    
                [archive_year_page] => Array
                    (
                        [url] => /[year:digital:4]/page/[page:digital]/
                        [widget] => Widget_Archive
                        [action] => render
                        [regx] => |^/([0-9]{4})/page/([0-9]+)[/]?$|
                        [format] => /%s/page/%s/
                        [params] => Array
                            (
                                [0] => year
                                [1] => page
                            )
    
                    )
    
                [archive_month_page] => Array
                    (
                        [url] => /[year:digital:4]/[month:digital:2]/page/[page:digital]/
                        [widget] => Widget_Archive
                        [action] => render
                        [regx] => |^/([0-9]{4})/([0-9]{2})/page/([0-9]+)[/]?$|
                        [format] => /%s/%s/page/%s/
                        [params] => Array
                            (
                                [0] => year
                                [1] => month
                                [2] => page
                            )
    
                    )
    
                [archive_day_page] => Array
                    (
                        [url] => /[year:digital:4]/[month:digital:2]/[day:digital:2]/page/[page:digital]/
                        [widget] => Widget_Archive
                        [action] => render
                        [regx] => |^/([0-9]{4})/([0-9]{2})/([0-9]{2})/page/([0-9]+)[/]?$|
                        [format] => /%s/%s/%s/page/%s/
                        [params] => Array
                            (
                                [0] => year
                                [1] => month
                                [2] => day
                                [3] => page
                            )
    
                    )
    
                [comment_page] => Array
                    (
                        [url] => [permalink:string]/comment-page-[commentPage:digital]
                        [widget] => Widget_Archive
                        [action] => render
                        [regx] => |^(.+)/comment-page-([0-9]+)[/]?$|
                        [format] => %s/comment-page-%s
                        [params] => Array
                            (
                                [0] => permalink
                                [1] => commentPage
                            )
    
                    )
    
                [feed] => Array
                    (
                        [url] => /feed[feed:string:0]
                        [widget] => Widget_Archive
                        [action] => feed
                        [regx] => |^/feed(.*)[/]?$|
                        [format] => /feed%s
                        [params] => Array
                            (
                                [0] => feed
                            )
    
                    )
    
                [feedback] => Array
                    (
                        [url] => [permalink:string]/[type:alpha]
                        [widget] => Widget_Feedback
                        [action] => action
                        [regx] => |^(.+)/([_0-9a-zA-Z-]+)[/]?$|
                        [format] => %s/%s
                        [params] => Array
                            (
                                [0] => permalink
                                [1] => type
                            )
    
                    )
    
                [page] => Array
                    (
                        [url] => /[slug].html
                        [widget] => Widget_Archive
                        [action] => render
                        [regx] => |^/([^/]+).html[/]?$|
                        [format] => /%s.html
                        [params] => Array
                            (
                                [0] => slug
                            )
    

    这个在代码里标为routingTable的东西其实就是程序对不同pathinfo的解析规则。

    剩下的活就交给index.php里的Typecho_Router::dispatch();

    这句的注释是/** 开始路由分发 */

    接着上边 pathinfo =/archives/1/的例子

    dispatch函数将路由表里的[regx]里的正则表达式一一进行正则匹配,发现与[post]的匹配,并1提取作为参数cid的值,并将参数cid=1作为参数提交给Widget_Archive类的render函数,Widget_Archive类根据类型postcid=1进行数据查询和模板渲染发送给客户端,至此一个简单的执行流程就完成了!

    细心的读者可能会发现,为什么系统路由里的怎么都是

    [widget] => Widget_Archive
    [action] => render
    

    这是因为typecho在类Widget_Archive里还根据不同的访问类型调用了不同的查询函数,这个以后再说!

  • 相关阅读:
    leetcode 268. Missing Number
    DBSCAN
    python二维数组初始化
    leetcode 661. Image Smoother
    leetcode 599. Minimum Index Sum of Two Lists
    Python中的sort() key含义
    leetcode 447. Number of Boomerangs
    leetcode 697. Degree of an Array
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(1月3日)
    北京Uber优步司机奖励政策(1月2日)
  • 原文地址:https://www.cnblogs.com/u0mo5/p/4583917.html
Copyright © 2020-2023  润新知