typecho流程原理和插件機制淺析(第二彈)

上一次說了 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 的你懂的~~

下一節,根據具體接口,演示插件編寫~

相關文章
相關標籤/搜索