Typecho是一个由国人开发的小型单用户博客程序。它的设计思想介于过程式编程(如Wordpress)以及现代的完全面向对象编程(如laravel框架)之间,算是一个过渡的产品。另外,Typecho整体结构设计清晰完整,代码量也不大,对于像我这样的初学者而言,为了更好的理解PHP编程的前世今生以及响应编程思想的发展,Typecho的源代码应该是一个很好的学习研究对象。
看代码先就从整体结构入手。Typecho整体的设计很有层次和条理的,整理归纳如下图:
核心层
核心层包括Typecho,IXR和CommonMark三个组件。其中Typecho是Typecho的框架层,相当于是专门为博客程序写的一个精简的框架系统。主要封装了数据库,路由,HTTP相关操作以及定义了widget和Plugin对象。
IXR是一个XML-RPC库用来远程发布文章,CommonMark是一个markdown的解析库,用来把Markdown文件渲染为html,这两个是Typecho使用到的外来第三方库。
Widget层
Widget层是在Typecho核心层上用来实现网站具体业务流程的。Typecho通过把每个小的操作都封装成Widget来保证系统的灵活性。路由系统最终是执行Widget对象的action方法,所以 Widget可以看成是“Typecho精简框架”上的MVC系统中的控制器(Controller)。
Plugin层
plugin层是为了系统的扩展性而开发的。在Typecho核心层和Widget层中作者预留了很多接口,通过plugin可以给这些接口设置回调函数来扩展整个系统。
前台后台
Typecho的前台和后台是分开来的两个系统,前台通过index.php作为唯一入口地址启动整个程序,而后台则使用admin/index.php作为唯一入口来启动后台程序。
Typecho程序启动流程
Typecho的启动代码主要在config.inc.php和index.php中,我们把两个文件的代码放在一起,来看一看具体的启动过程。
/** 定义目录相关的常量 */ define('__TYPECHO_ROOT_DIR__', dirname(__FILE__)); define('__TYPECHO_PLUGIN_DIR__', '/usr/plugins'); define('__TYPECHO_THEME_DIR__', '/usr/themes'); define('__TYPECHO_ADMIN_DIR__', '/admin/'); @set_include_path(get_include_path() . PATH_SEPARATOR . __TYPECHO_ROOT_DIR__ . '/var' . PATH_SEPARATOR . __TYPECHO_ROOT_DIR__ . __TYPECHO_PLUGIN_DIR__); /** 载入Typecho核心层必要的文件 */ require_once 'Typecho/Common.php'; require_once 'Typecho/Response.php'; require_once 'Typecho/Config.php'; require_once 'Typecho/Exception.php'; require_once 'Typecho/Plugin.php'; require_once 'Typecho/I18n.php'; require_once 'Typecho/Db.php'; require_once 'Typecho/Router.php'; /** 执行系统初始化,设置全局自动载入和异常截获函数 */ Typecho_Common::init(); /** 设置并初始化数据库连接 */ $db = new Typecho_Db('Mysql', 'typecho_'); $db->addServer(array ( 'host' => 'localhost', 'user' => '', 'password' => 'local', 'charset' => 'utf8', 'port' => '3306', 'database' => '', ), Typecho_Db::READ | Typecho_Db::WRITE); Typecho_Db::set($db); /** 由初始化组件(Widget_Init)启动Typecho,具体执行的过程有: 从数据库中取出所有设置,保存在$options中, 初始化语言包, 初始化cookie, 初始化charset, 初始化exception, 设置用户请求的URL, **初始化路由器**, 初始化插件系统, 初始化响应头, 初始化时区, 开始会话, 开始监听缓冲区。 */ Typecho_Widget::widget('Widget_Init'); /** 注册一个初始化插件,这里就是插件的一个入口点 如果想在程序执行前运行代码,通过插件设置这里的回调函数即可。 */ Typecho_Plugin::factory('index.php')->begin(); /** 开始路由分发 */ Typecho_Router::dispatch(); /** 注册一个结束插件,另一个插件入口点,程序执行完后运行 */ Typecho_Plugin::factory('index.php')->end();
整个过程很清晰,先通过Typecho_Widget::widget('Widget_Init')这个Widget做各种初始化操作,包括最重要的初始化路由表和插件系统,然后通过Typecho_Router::dispatch()分发开始分发路由。