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!

推薦閱讀: