thinkphp插件鉤子的實現機制是什么

    現在主流的cms或者blog等系統中,都內置的有插件系統,但是層層深入、剖析實現的方式,其實都是最簡單的鉤子的復雜化的實現。

    前言

    插件的執行通過鉤子來觸發;可以把插件看作掛在鉤子上的東西;插件只有在成功實現相應鉤子方法并被正確安裝啟用后才能執行。

    開發者也可以用hook(‘test’)方法在控制器只加入鉤子,讓你的應用具有更好的擴展性;同時也可以模板里加入鉤子{:hook(‘footer’)};鉤子也支持傳入參數hook(‘footer’,Array(‘test’=>1));

    向系統暴露你的鉤子,就是把你的鉤子在相應的文件里列出來,系統會來檢測。

    {:hooks('documentDetailAfter')}

    這個的意思就是:相當于在這邊 打一個點 ,我們可以將插件掛載到那
    官方的說法是:文檔末尾顯示顯示的 鉤子
    意思就是說,在文檔末尾的時候,會自動調用掛載在那個 鉤子 上的插件

    立即學習PHP免費學習筆記(深入)”;

    舉例說明

    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 addonsdemo;     class Demo{         public function registerBefore(){             echo &#39;registerBefore&#39;.&#39;</br>'; ????????} ????????public?function?registerAfter(){ ????????????echo?'registerAfter'.''; ????????}???? ????}

    插件實現的地方,即上文的注冊的文件:

    ????<?php     namespace indexcontroller;     use hookHook;     class Index{         public function index(){             Hook::run(&#39;registerBefore&#39;);             echo &#39;注冊完成&#39;.&#39;</br>'; ????????????Hook::run('registerAfter'); ???????????? ????????} ????}

    入口文件index.php

    ????<?php     use indexcontrollerIndex;     spl_autoload_register(&#39;autoload&#39;);     function autoload($name){         require_once(&#39;/&#39;.str_replace(&#39;&#39;,&#39;/&#39;,$name).&#39;.php&#39;);     }     //插件注冊     hookHook::add(&#39;registerBefore&#39;,&#39;addonsdemoDemo&#39;);     hookHook::add(&#39;registerAfter&#39;,&#39;addonsdemoDemo&#39;);     //調用     $index = new Index();     $index->index();

    運行接口如下:

    ????registerBefore????注冊完成????registerAfter

    如果要添加新的功能,程序員只要修改demo的插件就可,如果要拓展新的功能,只需要拓展registerBefore和registerAfter即可。?

    以上就是

    ? 版權聲明
    THE END
    喜歡就支持一下吧
    點贊7 分享