php插件機制實現原理


插件,亦即Plug-in,是指一類特定的功能模塊(通常由第三方開發者實現)

它的特點: 
1. 隨時安裝、卸載、激活、禁用
2. 無論什么狀態都不影響系統核心模塊的運行,
3. 是一種非侵入式的模塊化設計,實現了核心程序與插件程序的松散耦合。

一個健壯的PHP插件機制,我認為必須具備以下特點: 
1. 插件的動態監聽和加載(Lookup)
2. 插件的動態觸發 
以上兩點的PHP插件機制實現均不影響核心程序的運行

鈎子(Hooks) 
要在程序中實現插件,我們首先應該想到的就是定義不同的鈎子(Hooks);“鈎子”是一個很形象的邏輯概念,你可以認為它是系統預留的插件觸發條件。
它的邏輯原理如下:

當系統執行到某個鈎子時,會判斷這個鈎子的條件是否滿足;

如果滿足,會轉而先去調用鈎子所制定的功能,然后返回繼續執行余下的程序;

如果不滿足,跳過即可。這有點像匯編中的“中斷保護”邏輯。

某些鈎子可能是系統事先就設計好的,比如之前我舉的關於評論Spam過濾的鈎子,通常它已經由核心系統開發人員設計進了評論的處理邏輯中;另外一類鈎子則可能是由用戶自行定制的(由第三方開發人員制定),通常存在於表現層,比如一個普通的PHP表單顯示頁面中。

整個機制核心分為三大塊:

1.一個插件經理類:

這是核心之核心。它是一個應用程序全局Global對象。它主要有三個職責: 
負責監聽已經注冊了的所有插件,並實例化這些插件對象。 
負責注冊所有插件。 
當鈎子條件滿足時,觸發對應的對象方法。

2.插件的功能實現:

這大多由第三方開發人員完成,但需要遵循一定的規則,這個規則是插件機制所規定的,因插件機制的不同而不同,下面的顯示代碼你會看到這個規則。

3.插件的觸發:

也就是鈎子的觸發條件。具體來說這是一小段代碼,放置在你需要插件實現的地方,用於觸發這個鈎子。

 

插件經理PluginManager類:
 1 <?php
 2 
 3 class PluginManager {
 4 
 5     private $_listeners = array();
 6 
 7     public function __construct() {
 8         //這里$plugin數組包含我們獲取已經由用戶
 9         //激活的插件信息
10         //為演示方便,我們假定$plugin中至少包含  
11         //$plugin = array(  
12         // 'name' => '插件名稱',  
13         // 'directory'=>'插件安裝目錄'  
14         //);  
15         $plugins = array(
16             array(
17                 'name' => '插件名稱',
18                 'directory' => '插件安裝目錄'
19             )
20         );
21         //這個函數請自行實現  
22         if ($plugins) {
23             foreach ($plugins as $plugin) {
24                 ////假定每個插件文件夾中包含一個actions.
25                 //php文件,它是插件的具體實現
26                 if (@file_exists(STPATH . 'plugins/' . $plugin['directory'] . '/actions.php')) {
27                     include_once(STPATH . 'plugins/' . $plugin['directory'] . '/actions.php');
28                     $class = $plugin['name'] . '_actions';
29                     if (class_exists($class)) {
30                         //初始化所有插件
31                         new $class($this);
32                     }
33                 }
34             }
35         }
36         //此處做些日志記錄方面的東西  
37     }
38 
39     function register($hook, &$reference, $method) {
40         //獲取插件要實現的方法  
41         $key = get_class($reference) . '->' . $method;
42         //將插件的引用連同方法push進監聽數組中  
43         $this->_listeners[$hook][$key] =
44                 array(&$reference, $method);
45         //此處做些日志記錄方面的東西  
46     }
47 
48     function trigger($hook, $data = '') {
49         $result = '';
50         //查看要實現的鈎子,是否在監聽數組之中  
51         if (isset($this->_listeners[$hook]) && is_array($this->_listeners[$hook]) && count($this->_listeners[$hook]) > 0) {
52             // 循環調用開始  
53             foreach ($this->_listeners[$hook] as $listener) {
54                 // 取出插件對象的引用和方法  
55                 $class = & $listener[0];
56                 $method = $listener[1];
57                 if (method_exists($class, $method)) {
58                     // 動態調用插件的方法  
59                     $result .= $class->$method($data);
60                 }
61             }
62         }
63         //此處做些日志記錄方面的東西  
64         return $result;
65     }
66 
67 }
68 
69 ?>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM