thinkphp(php)插件鉤子(hooks)分析的簡單實現機制
現在主流的cms或者blog等系統中,都內置的有插件系統,但是層層深入、剖析實現的方式,其實都是最簡單的鉤子的復雜化的實現。
前言
鉤子是插件執行的觸發器;插件就像掛在鉤子上的東西;插件隻有實現相應鉤子方法,並安裝啟用成功後才能執行。
開發者也可以用hook('test')方法在控制器隻加入鉤子,讓你的應用具有更好的擴展性;同時也可以模板裡加入鉤子{:hook('footer')};鉤子也支持傳入參數hook('footer',array('test'=>1));
向系統暴露你的鉤子,就是把你的鉤子在相應的文件裡列出來,系統會來檢測。
{:hooks('documentDetailAfter')}
這個的意思就是:相當於在這邊 打一個點 ,我們可以將插件掛載到那
官方的說法是:文檔末尾顯示顯示的 鉤子
意思就是說,在文檔末尾的時候,會自動調用掛載在那個 鉤子 上的插件
舉例說明
php中所謂的鉤子,其實就是一種事件驅動,主要分為‘註冊事件’、‘觸發事件’兩步。所謂‘註冊事件’,即目的是給未來可能發生的'事情'起一個名字,名字,可以用單例模式或者註冊 為一個全局的變量,用的時候直接在對應的方法或者類再或者函數中插入這個變量即可;‘觸發事件’,本質上就是在事件的全局變量中查詢要觸發的時間名稱,然後找到註冊號的類與方法,實例化運行。
舉個例子來說明一下。
項目經理給我們瞭如下的需求:
第一天:開發註冊的功能。
程序員巴拉巴拉,三下五除二就完成瞭。
第二天:在註冊前添加發送短信驗證碼的功能。
程序員巴拉巴拉,三峽五除二就又完成瞭。
第三天:註冊完成之後,給用戶添加相應的積分。
程序員又開始巴拉巴拉ing……
class Register{ public function index(){ /** * 第二天發送短信功能 */ /** * 第一天註冊代碼 */ /** * 第三天增加積分功能 */ } }
這樣一個人開發還好,多個人開發,勢必會造成配合麻煩的問題,同時代碼也會變得混亂。
作為優秀程序員的我們,當然不容許我們程序中代碼冗餘、混亂的出現,於是我們把方法寫成函數獨立出來,方便調用與代碼簡介。於是形成如下代碼:
class Register{ public function index(){ /** * 第二天發送短信功能 */ sendMsg($data); /** * 第一天註冊代碼 */ /** * 第三天增加積分功能 */ sendIntegral($data); } } /** * 發送短信 * @param {[type]} $data [description] * @return {[type]} [description] */ function sendMsg($data){ /* balabala */ } /** * 贈送積分 * @param {[type]} $data [description] * @return {[type]} [description] */ function sendIntegral($data){ /* balabala */ }
但是我們想要把程序開元出去讓更多的人參與,這種直接修改源碼碼的方式始終不是太好,這個時候,我們就可以使用鉤子的方式,在註冊成功前後註冊兩個鉤子,我們隻需要把鉤子告訴開發人員就行瞭,這樣他們不用改變源碼碼就可以輕易的進行拓展。
class Register{ public function index(){ //註冊前鉤子 Hook::run('registerBefore'); /** * 註冊代碼 */ //註冊後鉤子 Hook::run('registerAfter'); } }
鉤子的簡單實現代碼
目錄結構:../hook/Hook.php
鉤子核心類Hook.php:
<?php namespace hook; class Hook{ static protected $hook = []; /** * 插件註冊 * @param [type] $name [description] * @param [type] $addons [description] */ static public function add($name,$addons){ self::$hook[$name] = $addons; } /** * 插件執行 * @param [type] $name [description] * @return [type] [description] */ static public function run($name){ if(isset(self::$hook[$name])){ $method = (new self::$hook[$name]()); call_user_func([$method,$name]); } } }
簡單的插件demo:
<?php namespace addons\demo; class Demo{ public function registerBefore(){ echo 'registerBefore'.'</br>'; } public function registerAfter(){ echo 'registerAfter'.'</br>'; } }
插件實現的地方,即上文的註冊的文件:
<?php namespace index\controller; use hook\Hook; class Index{ public function index(){ Hook::run('registerBefore'); echo '註冊完成'.'</br>'; Hook::run('registerAfter'); } }
入口文件index.php
<?php use index\controller\Index; spl_autoload_register('autoload'); function autoload($name){ require_once('/'.str_replace('\\','/',$name).'.php'); } //插件註冊 hook\Hook::add('registerBefore','\\addons\\demo\\Demo'); hook\Hook::add('registerAfter','\\addons\\demo\\Demo'); //調用 $index = new Index(); $index->index();
運行接口如下:
- registerBefore
- 註冊完成
- registerAfter
如果要添加新的功能,程序員隻要修改demo的插件就可,如果要拓展新的功能,隻需要拓展registerBefore和registerAfter即可。
總結
可以說,鉤子就是掛載點。
掛載點:在系統中提供給你一個掛載點,我們可以進行插件開發,開發完成後,我們將其掛載到 掛載點上,會自動調用執行。
到此這篇關於thinkphp(php)插件鉤子(hooks)分析的簡單實現機制的文章就介紹到這瞭,更多相關php插件鉤子(hooks)內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!