上一次说了 Typecho 大体的流程,今天简单说一下插件机制和插件的编写方法。php
仍是先上index.php数据库
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();
细心的朋友可能会发现上一次函数
/** 注册一个初始化插件 */ Typecho_Plugin::factory('index.php')->begin(); /** 注册一个结束插件 */ Typecho_Plugin::factory('index.php')->end();
这两行代码咱们并无提起,这是为何呢?这是由于上一期主要是分析系统执行流程,咱们假设没有安装任何插件,而在没有安装插件的状况下这两行代码是没有任何做用的。typecho
众所周知,目前大部分插件都采用钩子机制,Typecho也不例外,这两行代码就是系统在index.php里预先设定的两个插件接口,分别是整个程序流程中第一个和最后一个接口。那这种插件接口是怎么执行的呢?this
咱们以 HelloWorld
插件为例,HelloWorld
插件所使用的接口在 admin/menu.php
,代码以下:spa
<?php Typecho_Plugin::factory('admin/menu.php')->navBar(); ?>
HelloWorld
插件的代码,在 usr/plugins/HelloWorld/Plugins.php
:插件
<?php /** * Hello World * * @package HelloWorld * @author qining * @version 1.0.0 * @link http://typecho.org */ class HelloWorld_Plugin implements Typecho_Plugin_Interface { /** * 激活插件方法,若是激活失败,直接抛出异常 * * @access public * @return void * @throws Typecho_Plugin_Exception */ public static function activate() { Typecho_Plugin::factory('admin/menu.php')->navBar = array('HelloWorld_Plugin', 'render'); } /** * 禁用插件方法,若是禁用失败,直接抛出异常 * * @static * @access public * @return void * @throws Typecho_Plugin_Exception */ public static function deactivate(){} /** * 获取插件配置面板 * * @access public * @param Typecho_Widget_Helper_Form $form 配置面板 * @return void */ public static function config(Typecho_Widget_Helper_Form $form) { /** 分类名称 */ $name = new Typecho_Widget_Helper_Form_Element_Text('word', NULL, 'Hello World', _t('说点什么')); $form->addInput($name); } /** * 我的用户的配置面板 * * @access public * @param Typecho_Widget_Helper_Form $form * @return void */ public static function personalConfig(Typecho_Widget_Helper_Form $form){} /** * 插件实现方法 * * @access public * @return void */ public static function render() { echo '<span class="message success">' . Typecho_Widget::widget('Widget_Options')->plugin('HelloWorld')->word . '</span>'; } }
Typecho 在数据库 Options 表里,有一个名为 plugins
字段,里边记录了整个程序已激活插件的接口挂载状况,没有激活任何插件时 plugins
字段是这样的:code
Array ( [activated] => Array ( ) [handles] => Array ( ) )
接下来咱们激活程序自带的 HelloWorld 插件看看有什么变化,激活后 plugins
字段变为:orm
Array ( [activated] => Array ( [HelloWorld] => Array ( [handles] => Array ( [admin/menu.php:navBar] => Array ( [0] => Array ( [0] => HelloWorld_Plugin [1] => render ) ) ) ) ) [handles] => Array ( [admin/menu.php:navBar] => Array ( [0] => Array ( [0] => HelloWorld_Plugin [1] => render ) ) ) )
能够看出,激活插件后,程序根据插件的激活函数接口
public static function activate() { Typecho_Plugin::factory('admin/menu.php')->navBar = array('HelloWorld_Plugin', 'render'); }
系统在数据库中将 HelloWorld
插件与 ('admin/menu.php')->navBar()
接口做了关联,
而具体关联的则是 HelloWorld_Plugin
类的 render
函数。
其实到这里你们也能看出个大概,咱们访问系统后台的时候,当执行到
<?php Typecho_Plugin::factory('admin/menu.php')->navBar(); ?>
这句代码时:
从数据库 plugins
字段里检索,检索到 [admin/menu.php:navBar]
下挂载了一个插件,具体为 HelloWorld_Plugin
类的 render
函数,系统执行之并输出 HelloWorld
在后台的导航栏。
那么若是检索不到有任何插件挂载呢,程序不执行任何动做并执行下边的代码,这也就是为何在分析系统流程时能够直接将插件接口的代码略过的缘由。
整个程序中关键的地方设置了不少相似的插件接口,方便经过编写插件而不修改程序源代码来完成咱们特定的功能,设置插件接口的方法有两种:
一种是 Typecho_Plugin::factory
,在 var/Typecho/Plugin.php
中定义
另外一种是 $this->pluginHandle()
, 在 var/Typecho/Widget.php
中定义
第二种是能够传递参数的接口,这个之后再说。
最后不由有人要问,程序中设定这么多接口,即便一个插件也没安装也要挨个执行吗,效率得多低?
答案是确定的,必须得执行,不过数据库也只读取一次,而后存在内存里,之后的每次查询都是在内存对比,多执行两行php代码基本没效率影响。具体速度咋样,用过 wp 的你懂的~~
下一节,根据具体接口,演示插件编写~