本篇文章主要介紹了PHP中如何實現Hook機制,詳細的介紹了Hook機制的原理和實現過程,具有一定的參考價值,有興趣的可以了解一下
對"鉤子"這個概念其實不熟悉,最近看到一個php框架中用到這個機制來擴展項目,所以大概來了解下。
所謂Hook機制,是從Windows程式設計中流行開的技術。其主要思想是提前在可能增加功能的地方埋好(預設)一個鉤子,這個鉤子並沒有實際的意義,當我們需要重新修改或者增加這個地方的邏輯的時候,把擴展的類或者方法掛載到這個點即可。
hook外掛機制的基本概念:
在專案程式碼中,你認為要擴充(暫時不擴充)的地方放置一個鉤子函數,等需要擴充的時候,把需要實作的類別和函數掛載到這個鉤子上,就可以實現擴充了。
想法就是這樣聽起來比較籠統,看一個網路上的實現的例子。
整個外掛機制包含三個部分:
1.hook外掛程式經理類別:這個是核心文件,是一個應用程式全域Global物件。它主要有三個職責
1>監聽已經註冊了的所有插件,並實例化這些插件物件。
2>註冊所有外掛程式。
3>當鉤子條件滿足時,觸發對應的物件方法。
2.外掛程式的功能實作:這大多由第三方開發人員完成,但需要遵循我們(經理類定義)的規則,這個規則是外掛機制所規定的,因外掛機制的不同而不同。
3.外掛程式的觸發:也就是鉤子的觸發條件。這是一小段程式碼,放置在你需要呼叫插件的地方,用於觸發這個鉤子。
----------------------------------看一看別人實現的方案--- -----------------------------
首先是外掛程式經理類別PluginManager,這個類別要放在全域引用裡面,在所有需要用到插件的地方,優先載入。
<?php /** * * 插件机制的实现核心类 */ class PluginManager { /** * 监听已注册的插件 * * @access private * @var array */ private $_listeners = array(); /** * 构造函数 * * @access public * @return void */ public function __construct() { #这里$plugin数组包含我们获取已经由用户激活的插件信息 #为演示方便,我们假定$plugin中至少包含 #$plugin = array( # 'name' => '插件名称', # 'directory'=>'插件安装目录' #); $plugins = get_active_plugins();#这个函数请自行实现 if($plugins) { foreach($plugins as $plugin) {//假定每个插件文件夹中包含一个actions.php文件,它是插件的具体实现 if (@file_exists(STPATH .'plugins/'.$plugin['directory'].'/actions.php')) { include_once(STPATH .'plugins/'.$plugin['directory'].'/actions.php'); $class = $plugin['name'].'_actions'; if (class_exists($class)) { //初始化所有插件 new $class($this); } } } } #此处做些日志记录方面的东西 } /** * 注册需要监听的插件方法(钩子) * * @param string $hook * @param object $reference * @param string $method */ function register($hook, &$reference, $method) { //获取插件要实现的方法 $key = get_class($reference).'->'.$method; //将插件的引用连同方法push进监听数组中 $this->_listeners[$hook][$key] = array(&$reference, $method); #此处做些日志记录方面的东西 } /** * 触发一个钩子 * * @param string $hook 钩子的名称 * @param mixed $data 钩子的入参 * @return mixed */ function trigger($hook, $data='') { $result = ''; //查看要实现的钩子,是否在监听数组之中 if (isset($this->_listeners[$hook]) && is_array($this->_listeners[$hook]) && count($this->_listeners[$hook]) > 0) { // 循环调用开始 foreach ($this->_listeners[$hook] as $listener) { // 取出插件对象的引用和方法 $class =& $listener[0]; $method = $listener[1]; if(method_exists($class,$method)) { // 动态调用插件的方法 $result .= $class->$method($data); } } } #此处做些日志记录方面的东西 return $result; } }
接下來是一個簡單外掛程式的實作DEMO_actions。這是一個簡單的Hello World插件,用於輸出一句話。在實際情況中,say_hello可能包括對資料庫的操作,或者是其他一些特定的邏輯。
<?php /** * 这是一个Hello World简单插件的实现 */ /** *需要注意的几个默认规则: * 1. 本插件类的文件名必须是action * 2. 插件类的名称必须是{插件名_actions} */ class DEMO_actions { //解析函数的参数是pluginManager的引用 function __construct(&$pluginManager) { //注册这个插件 //第一个参数是钩子的名称 //第二个参数是pluginManager的引用 //第三个是插件所执行的方法 $pluginManager->register('demo', $this, 'say_hello'); } function say_hello() { echo 'Hello World'; } }
再接下來就是插件的呼叫觸發的地方,例如我要將say_hello放到我部落格首頁Index.php, 那你在index.php中的某個位置寫下:
$pluginManager->trigger('demo','');
第一個參數表示鉤子的名字,第二個參數是插件對應方法的入口參數,由於這個例子中沒有輸入參數,所以為空。
這樣一個例子基本上很明確的表達了"鉤子"插件機制的實作方式和邏輯。
相關推薦:
#
以上是PHP中如何實作Hook機制的詳細內容。更多資訊請關注PHP中文網其他相關文章!