typecho源代码解析4---业务逻辑

上一节 这篇我们就讲讲首页的业务逻辑,首先我们看看路由。 [index] => Array ( [url] => / [widget] => Widget_Archive [action] => render [regx] => |^[/]?$| [format] => / [params] => Array ( ) ) 由路由表中的正则表达式我们能看出首页的URL为https://blog.phpgao.com/或http://www.phpgao.com,并且不接受任何参数。 下面我们找到了Widget_Archive类,让我们先看看这个类的继承关系(其中Typecho_Widget和Widget_Abstract为抽象类): 由上一节我们可以得到结论,当路由表匹配到/,会实例化Widget_Archive类,他位于var/Widget/Archive.php,其方法为render。 下面我们一步步跟进,看看到底发生了些什么? 再深入之前,我们需要有一些基本的概念,在此需要讲清楚,便于理解typecho的设计模式: 基类Typecho_Widget 该类位于var/Typecho/Widget.php,是var/Widget文件夹下所有类的基类,也就是说,几乎所有与业务有关的功能,就是继承此类。 纵观此类,方法不是很多,老高在此挑几个重要的讲解: /** * 获取对象插件句柄 * 此方法为插件的实现提供了快捷的语法 */ public function pluginHandle($handle = NULL) { return Typecho_Plugin::factory(empty($handle) ? get_class($this) : $handle); } /** * 将类本身赋值 * 模板中很常见,将自己复制给某一个变量,在调用next()方法循环输出 */ public function to(&$variable) { return $variable = $this; } /** * 将每一行的值压入堆栈 * 把数据放到自己的'肚子'里 */ public function push(array $value) { //将行数据按顺序置位 $this->row = $value; $this->length ++; $this->stack[] = $value; return $value; } /** * 返回堆栈每一行的值 * 有点像从数据库中循环读取结果集 * 与push相对应,值得大家参考 */ public function next() { if ($this->stack) { $this->row = @$this->stack[key($this->stack)]; next($this->stack); $this->sequence ++; } if (!...

October 14, 2014 · 1 min · Me

typecho源代码解析2---插件机制

上一节 上次我们讲到了系统完成了初始化,这一篇我们会更加深入typecho,同时会介绍typecho的插件机制。 插件点 热心的读者肯定会问,什么是插件点?当然你会不知道,因为这个名词是老高想出来的ಠ౪ಠ,本次要讲的插件机制的基础知识可以参考我的另一片博文thinkphp钩子的实现。钩子这个词比较粗俗,其实高大上的叫法就是插件,而老高自创的插件点就是事件的意思。 index.php中Typecho_Plugin::factory('index.php')->begin(),其实就是通知挂载到’index.php’这个事件的插件可以执行了。 具体流程如下: Typecho_Plugin::factory(‘index.php’)返回了Typecho_Plugin的实例,构造函数中确定了唯一的句柄,即’index.php',紧接着执行了该实例的begin()方法,由于该方法不存在,所以调用了魔术方法__call,最后由__call方法执行所有在这个插件点挂载的插件。 __call方法源代码: public function __call($component, $args) { $component = $this->_handle . ':' . $component; $last = count($args); $args[$last] = $last > 0 ? $args[0] : false; if (isset(self::$_plugins['handles'][$component])) { $args[$last] = NULL; $this->_signal = true; foreach (self::$_plugins['handles'][$component] as $callback) { $args[$last] = call_user_func_array($callback, $args); } } return $args[$last]; } 关键点: __call是可以带参数的 $callback是二位数组,一个类名,一个方法名 在该类init方法中,activated和handles是分开保存的,因为activated以插件名做键名,而handles以插件点为键,目的不同 插件的关联信息保存在数据库中typecho_options表中的plugins 需要禁用再启用才能使修改后的插件生效 当完成了第一个插件点的挂载后,程序开始路由分发。 下一节 码字不易,转载请注明出处。

October 12, 2014 · 1 min · Me

typecho源代码解析3---路由分发

上一节 时光匆匆,我们终于来到路由工作的地方。几乎每个MVC框架都不会缺少路由功能,因为他实在太重要了。 路由的功能简单的说就是根据请求找到对应业务代码,请求来自外部,业务由系统提供,路由器为二者建立了可靠的链接。 typecho和thinkphp都有路由模块,虽然实现方式不同,但用法却惊人的相似! thinkphp: Dispatcher::dispatch(); typecho: Typecho_Router::dispatch(); typecho的路由实现是保存在数据库中的路由表,使用正则匹配路径,这一点和Django框架有点像,thinkphp则是基于自己设定的一套规则,详见官方文档。 typecho的路由表如下数组组成,路由器类会使用子数组中的regx正则式逐个匹配pathinfo中的路径,如果匹配成功,立即初始化并执行该类对应的action。 以index为例,如果使用正则表达式匹配成功,系统就会新建Widget_Archive类并执行其render方法,看他的名字就知道执行的是渲染页面的方法,也就是之前说的业务。 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 ( ) ) # .... 有的同学可能会说,typecho的路由表写在数据库里,不够灵活。其实作者也考虑到了,大家可以自由扩展路由表。有兴趣的同学可以去看看Helper类中addRoute和removeRoute的用法。举个例子,如果你需要自定义一个URL,比如www.phpgao.com/robots.txt,就可以在路由表加入如下路由: [robots] => Array ( [url] => /robots....

October 12, 2014 · 1 min · Me

typecho源代码解析1---系统初始化

首先恭喜typecho v1.0的上线! 其次,这篇文章同thinkphp的源代码解析一样都是老高谋划了很久的文章,国庆节由于单位加班没有时间写,今天终于等来了轮休,果断放开了写。希望大家多多支持! 最后老高想说的是,如果大家有兴趣研究源码,那么问题来了,如何高效的学习研究源代码? 老高的建议是: 一定要熟悉MVC模式(针对WEB开发) 先看看文档再动手 分辨什么是好的坏的代码,不要搞盲目崇拜 做笔记 以下: 文档 如果有什么不明白的,文档里也许会找到答案。 typecho开发文档 版本 再研究源代码前,如果知道自己使用的typecho的版本呢? 答案写在var/Typecho/Common.php里,Typecho_Common类中的常量VERSION。 例子: class Typecho_Common { /** 程序版本 */ const VERSION = '1.0/14.10.9'; ... } 开启DEBUG模式 有些同学可能已经发现,typecho默认对外隐藏了PHP的错误信息,如果我们想要看到真正的报错信息,需要开启typecho的DEBUG模式,也可以叫做开发模式。当我们开启了这个模式后,在开发插件或者了解系统原理的时候就能够得到可视化的错误信息了。 开启方法: # 修改/config.inc.php # 在代码的第一行加入 /**开启debug模式*/ define('__TYPECHO_DEBUG__',1); ps.调试的时候如果你的服务器没有安装xdebug,那么你的var_dump()信息会没有格式。 在此老高推荐使用TP框架内的方法dump(),以后我们就可以使用dump()打印变量信息了。 # 修改/config.inc.php # 在debug后加入 /** * 浏览器友好的变量输出 * @param mixed $var 变量 * @param boolean $echo 是否输出 默认为True 如果为false 则返回输出字符串 * @param string $label 标签 默认为空 * @param boolean $strict 是否严谨 默认为true * @return void|string */ function dump($var, $echo=true, $label=null, $strict=true) { $label = ($label === null) ?...

October 11, 2014 · 2 min · Me