生活随笔
收集整理的這篇文章主要介紹了
PHP中插件机制的一种实现方案
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
插件,亦即Plug-in,是指一類特定的功能模塊(通常由第三方開發者實現),它的特點是:當你需要它的時候激活它,不需要它的時候禁用/刪除它;且無 論是激活還是禁用都不影響系統核心模塊的運行,也就是說插件是一種非侵入式的模塊化設計,實現了核心程序與插件程序的松散耦合。一個典型的例子就是 Wordpress中眾多的第三方插件,比如Akimet插件用于對用戶的評論進行Spam過濾。
一個健壯的插件機制,我認為必須具備以下特點:
- 插件的動態監聽和加載(Lookup)?
- 插件的動態觸發?
- 以上兩點的實現均不影響核心程序的運行
?
要在程序中實現插件,我們首先應該想到的就是定義不同的鉤子(Hooks);“鉤子”是一個很形象的邏輯概念,你可以認為它是系統預留的插件觸發條件。它 的邏輯原理如下:當系統執行到某個鉤子時,會判斷這個鉤子的條件是否滿足;如果滿足,會轉而先去調用鉤子所制定的功能,然后返回繼續執行余下的程序;如果 不滿足,跳過即可。這有點像匯編中的“中斷保護”邏輯。
某些鉤子可能是系統事先就設計好的,比如之前我舉的關于評論Spam過濾的鉤子,通常它已經由核心系統開發人員設計進了評論的處理邏輯中;另外一類鉤子則 可能是由用戶自行定制的(由第三方開發人員制定),通常存在于表現層,比如一個普通的PHP表單顯示頁面中。
可能你感覺上面的話比較無聊,讓人昏昏欲睡;但是要看懂下面我寫的代碼,理解以上的原理是必不可少的。
下面進行PHP中插件機制的核心實現,整個機制核心分為三大塊:
- 一個插件經理類:這是核心之核心。它是一個應用程序全局Global對象。它主要有三個職責:?
- 負責監聽已經注冊了的所有插件,并實例化這些插件對象。?
- 負責注冊所有插件。?
- 當鉤子條件滿足時,觸發對應的對象方法。
- 插件的功能實現:這大多由第三方開發人員完成,但需要遵循一定的規則,這個規則是插件機制所規定的,因插件機制的不同而不同,下面的顯 示代碼你會看到這個規則。?
- 插件的觸發:也就是鉤子的觸發條件。具體來說這是一小段代碼,放置在你需要插件實現的地方,用于觸發這個鉤子。
?
原理講了一大堆,下面看看我的實現方案:
插件經理PluginManager類:
1 <?
2 /**
3 * STBLOG PluginManager Class
4 *
5 * 插件機制的實現核心類
6 *
7 * @package STBLOG
8 * @subpackage Libraries
9 * @category Libraries
10 * @author Saturn
11 */
12 class PluginManager
13 {
14 /**
15 * 監聽已注冊的插件
16 *
17 * @access private
18 * @var array
19 */
20 private $_listeners =
array();
21 /**
22 * 構造函數
23 *
24 * @access public
25 * @return void
26 */
27 public function __construct()
28 {
29 #這里$plugin數組包含我們獲取已經由用戶激活的插件信息
30 #為演示方便,我們假定$plugin中至少包含
31 #$plugin = array(
32 # 'name' => '插件名稱',
33 # 'directory'=>'插件安裝目錄'
34 #);
35 $plugins = get_active_plugins();
#這個函數請自行實現
36 if(
$plugins)
37 {
38 foreach(
$plugins as $plugin)
39 {
//假定每個插件文件夾中包含一個actions.php文件,它是插件的具體實現
40 if (@
file_exists(STPATH .'plugins/'.
$plugin['directory'].'/actions.php'
))
41 {
42 include_once(STPATH .'plugins/'.
$plugin['directory'].'/actions.php'
);
43 $class =
$plugin['name'].'_actions'
;
44 if (
class_exists(
$class))
45 {
46 //初始化所有插件
47 new $class(
$this);
48 }
49 }
50 }
51 }
52 #此處做些日志記錄方面的東西
53 }
54
55 /**
56 * 注冊需要監聽的插件方法(鉤子)
57 *
58 * @param string $hook
59 * @param object $reference
60 * @param string $method
61 */
62 function register(
$hook, &
$reference,
$method)
63 {
64 //獲取插件要實現的方法
65 $key =
get_class(
$reference).'->'.
$method;
66 //將插件的引用連同方法push進監聽數組中
67 $this->_listeners[
$hook][
$key] =
array(&
$reference,
$method);
68 #此處做些日志記錄方面的東西
69 }
70 /**
71 * 觸發一個鉤子
72 *
73 * @param string $hook 鉤子的名稱
74 * @param mixed $data 鉤子的入參
75 * @return mixed
76 */
77 function trigger(
$hook,
$data=''
)
78 {
79 $result = ''
;
80 //查看要實現的鉤子,是否在監聽數組之中
81 if (
isset(
$this->_listeners[
$hook]) &&
is_array(
$this->_listeners[
$hook]) &&
count(
$this->_listeners[
$hook]) > 0
)
82 {
83 // 循環調用開始
84 foreach (
$this->_listeners[
$hook]
as $listener)
85 {
86 // 取出插件對象的引用和方法
87 $class =&
$listener[0
];
88 $method =
$listener[1
];
89 if(
method_exists(
$class,
$method))
90 {
91 // 動態調用插件的方法
92 $result .=
$class->
$method(
$data);
93 }
94 }
95 }
96 #此處做些日志記錄方面的東西
97 return $result;
98 }
99 }
100 ?>
?
以上代碼加上注釋不超過100行,就完成了整個插件機制的核心。需要再次說明的是,你必須將它設置成全局類,在所有 需要用到插件的地方,優先加載。用#注釋的地方是你需要自行完成的部分,包括插件的獲取和日志記錄等等。
下面是一個簡單插件的實現。
1 <?
2 /**
3 * 這是一個Hello World簡單插件的實現
4 *
5 * @package DEMO
6 * @subpackage DEMO
7 * @category Plugins
8 * @author Saturn
9 */
10 /**
11 *需要注意的幾個默認規則:
12 * 1. 本插件類的文件名必須是action
13 * 2. 插件類的名稱必須是{插件名_actions}
14 */
15 class DEMO_actions
16 {
17 //解析函數的參數是pluginManager的引用
18 function __construct(&
$pluginManager)
19 {
20 //注冊這個插件
21 //第一個參數是鉤子的名稱
22 //第二個參數是pluginManager的引用
23 //第三個是插件所執行的方法
24 $pluginManager->register('demo',
$this, 'say_hello'
);
25 }
26
27 function say_hello()
28 {
29 echo 'Hello World'
;
30 }
31 }
32 ?>
?
這是一個簡單的Hello World插件,用于輸出一句話。在實際情況中,say_hello可能包括對數據庫的操作,或者是其他一些特定的邏輯,比如調用Akimet API。
插件實現的默認規則由核心系統開發者自行確定。比如本例的一些默認規則我在注釋中已經寫的很清楚,在此不在贅述。需要特別注意的是鉤子名稱不要重復。
最后一步,就是定義鉤子的觸發,你將鉤子放在哪里,上面這個插件的方法就會在哪里出發。比如我要將say_hello放到我博客首頁Index.php, 那么你在index.php中的某個位置寫下:
$pluginManager->trigger('demo','');
第一個參數表示鉤子的名字,在本例中它是demo;第二個參數是插件對應方法的入口參數,由于這個例子中沒有輸入參數,所以為空。
總結?
本篇文章介紹了插件機制在PHP中實現的一種方法和思路,以及我本人對插件機制的理解。初次接觸這個東西,可能會比較生澀,難以理解。但是當你結合真實的 例子,再想想程序的運行流程,思路可能會更清晰一些。
轉載于:https://www.cnblogs.com/tianakong/p/10760839.html
總結
以上是生活随笔為你收集整理的PHP中插件机制的一种实现方案的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。