Typecho 代码阅读笔记(三) - 插件机制
Typecho 代码阅读笔记(二) - 数据库访问
Typecho 代码阅读笔记(一) - 页面渲染及路由机制
转载请注明出处:http://blog.csdn.net/jh_zzz
以
index.php
为例:
/**
初始化组件
*/
Typecho_Widget::
widget('Widget_Init'
);
Init
的
execute
中会初始化
Typecho_Plugin
,这里
$options
->
plugins
是从数据库读出来后反序列化的:
Typecho_Plugin::
init($options
->
plugins);
init
中分别将
plugins
中的
activated
和
handles
单独保存,打印出来形式是这样的:
[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
)
)
)
继续看
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
>
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
);
}
}
__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
的新特性:)