Typecho 代碼閱讀筆記(三) - 插件機制

轉載請註明出處:http://blog.csdn.net/jh_zzzphp

 

以 index.php 爲例:數據庫

/** 初始化組件 */函數

Typecho_Widget:: widget('Widget_Init' );學習

 

Init 的 execute 中會初始化 Typecho_Plugin ,這裏 $options -> plugins 是從數據庫讀出來後反序列化的:this

Typecho_Plugin:: init($options -> plugins);.net

init 中分別將 plugins 中的 activated 和 handles 單獨保存,打印出來形式是這樣的:插件

    [activated] => Arraycomponent

        (blog

            [HelloWorld] => Arrayget

                (

                    [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

                        )

 

                )

)

 

繼續看 index.php :

/** 註冊一個初始化插件 */

Typecho_Plugin:: factory('index.php' )-> begin();

… 略過 …

/** 註冊一個結束插件 */

Typecho_Plugin:: factory('index.php' )-> end();

Typecho_Plugin:: factory 會根據 ’index.php’ 建立一個新的 Typecho_Plugin 。接下來的 begin() , end() 實際上都是不存在的,因而魔鬼方法 __call 被執行,

 

$component $this -> _handle ':' $component ;

$last count($args );

$args [$last $last $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 );

    }

}

 

__call 查找對應 index.php:begin 的 Typecho_Plugin ,若是找到的話,就會調用相應的方法。例如若是找到的是HelloWorld_Plugin ,則 HelloWorld_Plugin.render() 會被執行。

  (

  [0] => HelloWorld_Plugin

  [1] => render

)

 

簡單說一下 Plugin 是如何加載的,在 config.inc.php 中首先設置了包含路徑,插件路徑也在其中:

/** 設置包含路徑 */

set_include_path(get_include_path() PATH_SEPARATOR .

__TYPECHO_ROOT_DIR__ '/var' PATH_SEPARATOR .

__TYPECHO_ROOT_DIR__ __TYPECHO_PLUGIN_DIR__ );

 

HelloWorld_Plugin 此時還沒有被加載,因此當執行到 HelloWorld_Plugin.render() 時 ,Typecho_Common::__autoLoad 函數被執行,這裏會自動加載指定的插件文件:

include_once str_replace('_' , '/' , $className '.php' ;

例如對於 HelloWorld_Plugin ,文件就是 HelloWorld/Plugin.php ,由於 usr/plugin 目錄已經在包含的路徑中,因此這個文件能夠正常加載。

 

當初我學習 php 的時候仍是 php3 ,如今一些新特性我都不知道,這一段我看了半天才搞清楚,此次讀這些代碼瞭解了很多 php 的新特性:)

相關文章
相關標籤/搜索