久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      PHP鉤子機制原理及詳解

      PHP鉤子機制原理及詳解

      什么是鉤子?

      大家想必聽過插件,wordpress插件特別多,這個就是用鉤子機制實現(xiàn)的。

      當代碼在運行的過程中,我們預(yù)先在運行的幾個特殊點里執(zhí)行一些特殊方法:例如在運行方法(例如Blog::add的add方法)之前記錄輸入?yún)?shù)、運行方法之后記錄處理結(jié)果,這個運行方法之前、運行方法之后就是簡單的鉤子(掛載點),我們在這個鉤子上放置鉤子函數(shù)(記錄輸入?yún)?shù)、記錄處理結(jié)果),執(zhí)行一些和程序運行不相關(guān)的任務(wù)。

      <?php class Blog extends Controller{          public function add(){                  //some code         $res = $data;                  return $res;     } } $obj = new Blog(); Log::write($_REQUEST); $res =  $obj->add(); Log::write(json_encode($res));

      如果在運行方法之前放置的是一個OnBeforeRunActionCallback()的方法,這個方法可能最開始的時候是空的,但我們以后就可以不去修改原有代碼,直接在OnBeforeRunActionCallback()里面加代碼邏輯就可以了,例如記錄日志、參數(shù)過濾等等。

      <?php class Blog extends Controller{          public function add(){                  //some code         $res = $data;                  return $res;     } } $obj = new Blog(); OnBeforeRunActionCallback($_REQUEST); $obj->add(); OnAfterRunActionCallback($res); function OnBeforeRunActionCallback($param){     Log::write($param);         FilterParams($param); } function OnAfterRunActionCallback($res){     Log::write(json_encode($res)); }

      在項目代碼中,你認為要擴展(暫時不擴展)的地方放置一個鉤子函數(shù),等需要擴展的時候,把需要實現(xiàn)的類和函數(shù)掛載到這個鉤子上,就可以實現(xiàn)擴展了。

      原理

      實際的鉤子一般設(shè)計為一個類Hook,該類提供注冊插件到鉤子(add_hook)、觸發(fā)鉤子方法(trigger_hook)。注冊插件的時候?qū)⒉寮\行的可執(zhí)行方法存儲到鉤子對應(yīng)的數(shù)組里面。

      $_listeners = array(     'OnBeforeRunAction' => array(         'callback1',         'callback2',         'callback3',     ), ); //提前注冊插件到鉤子 add_hook('OnBeforeRunAction', 'callback4'); //特定地方執(zhí)行鉤子 trigger_hook('OnBeforeRunAction');

      當觸發(fā)鉤子的時候,將遍歷OnBeforeRunAction里注冊的回調(diào)方法,執(zhí)行對應(yīng)的回調(diào)方法,實現(xiàn)動態(tài)擴展功能。注冊的鉤子方法一般是匿名函數(shù):

      function trigger_hook($hook, $data=''){     //查看要實現(xiàn)的鉤子,是否在監(jiān)聽數(shù)組之中     if (isset($this->_listeners[$hook]) && is_array($this->_listeners[$hook]) && count($this->_listeners[$hook]) > 0)     {         // 循環(huán)調(diào)用開始         foreach ($this->_listeners[$hook] as $listener)         {             if(is_callable()){                 call_user_func($listener, $data);             }elseif(is_array($listener)){                 // 取出插件對象的引用和方法                 $class =& $listener[0];                 $method = $listener[1];                 if(method_exists($class,$method))                 {                     // 動態(tài)調(diào)用插件的方法                     $class->$method($data);                 }             }         }     } }

      如何實現(xiàn)?

      簡單的

      1、插件類Hook:提供注冊插件和執(zhí)行插件的方法,實際是往一個數(shù)組里存掛載點對應(yīng)的可執(zhí)行方法。

      2、在某個配置文件或者函數(shù)里統(tǒng)一注冊插件。

      class Hook {     //action hooks array       private static $actions = array();     /**      * ads a function to an action hook      * @param $hook      * @param $function      */     public static function add_action($hook,$function)     {            $hook=mb_strtolower($hook,CHARSET);         // create an array of function handlers if it doesn't already exist         if(!self::exists_action($hook))         {             self::$actions[$hook] = array();         }         // append the current function to the list of function handlers         if (is_callable($function))         {             self::$actions[$hook][] = $function;             return TRUE;         }         return FALSE ;     }     /**      * executes the functions for the given hook      * @param string $hook      * @param array $params      * @return boolean true if a hook was setted      */     public static function do_action($hook,$params=NULL)     {         $hook=mb_strtolower($hook,CHARSET);         if(isset(self::$actions[$hook]))         {             // call each function handler associated with this hook             foreach(self::$actions[$hook] as $function)             {                 if (is_array($params))                 {                     call_user_func_array($function,$params);                 }                 else                 {                     call_user_func($function);                 }                 //cant return anything since we are in a loop! dude!             }             return TRUE;         }         return FALSE;     }     /**      * gets the functions for the given hook      * @param string $hook      * @return mixed      */     public static function get_action($hook)     {         $hook=mb_strtolower($hook,CHARSET);         return (isset(self::$actions[$hook]))? self::$actions[$hook]:FALSE;     }     /**      * check exists the functions for the given hook      * @param string $hook      * @return boolean      */     public static function exists_action($hook)     {         $hook=mb_strtolower($hook,CHARSET);         return (isset(self::$actions[$hook]))? TRUE:FALSE;     } }       /**      * Hooks Shortcuts not in class      */     function add_action($hook,$function)     {         return Hook::add_action($hook,$function);     }       function do_action($hook)     {         return Hook::do_action($hook);     }

      用法舉例:

      //添加鉤子 Hook::add_action('unique_name_hook','some_class::hook_test'); //或使用快捷函數(shù)添加鉤子: add_action('unique_name_hook','other_class::hello'); add_action('unique_name_hook','some_public_function'); //執(zhí)行鉤子 do_action('unique_name_hook');//也可以使用 Hook::do_action();

      帶安裝/卸載的

      鉤子類初始化的時候去注冊已經(jīng)開啟的插件(如數(shù)據(jù)庫記錄);全局合適的時候設(shè)置掛載點;運行到合適的時候觸發(fā)掛載點注冊的事件。

      1、插件類Hook:提供注冊插件和執(zhí)行插件的方法,實際是往一個數(shù)組里存掛載點對應(yīng)的可執(zhí)行方法。

      2、插件類增加一個初始化的方法,去數(shù)據(jù)查找已經(jīng)安裝的插件,運行插件必須執(zhí)行的注冊方法(reg),注冊插件方法注冊鉤子到掛載點。

      3、固定把插件放在某個目錄,并安照一定規(guī)范寫配置文件。后臺有插件列表頁面,遍歷指定目錄下的插件。當安裝的時候,將插件信息記錄到數(shù)據(jù)庫,卸載的時候刪除數(shù)據(jù)庫記錄信息。

      <?php /**  * @file plugin.php  * @brief 插件核心類  * @note 觀察者模式,注冊事件,觸發(fā)事件  */ class plugin extends IInterceptorBase {     //默認開啟的插件列表     private static $defaultList = array("_verification","_goodsCategoryWidget","_authorization","_userInfo","_initData");     //已經(jīng)注冊監(jiān)聽     private static $_listen = array();     //加載插件     public static function init()     {         $pluginDB    = new IModel('plugin');         $pluginList  = $pluginDB->query("is_open = 1","class_name","sort asc");         //加載默認插件         foreach(self::$defaultList as $val)         {             $pluginList[]= array('class_name' => $val);         }         foreach($pluginList as $key => $val)         {             $className = $val['class_name'];             $classFile = self::path().$className."/".$className.".php";             if(is_file($classFile))             {                 include_once($classFile);                 $pluginObj = new $className();                 $pluginObj->reg();             }         }     }     /**      * @brief 注冊事件      * @param string $event 事件      * @param object ro function $classObj 類實例 或者 匿名函數(shù)      * @param string $method 方法名字      */     public static function reg($event,$classObj,$method = "")     {         if(!isset(self::$_listen[$event]))         {             self::$_listen[$event] = array();         }         self::$_listen[$event][] = array($classObj,$method);     }     /**      * @brief 顯示已注冊事件      * @param string $event 事件名稱      * @return array      */     public static function get($event = '')     {         if($event)         {             if( isset(self::$_listen[$event]) )             {                 return self::$_listen[$event];             }             return null;         }         return self::$_listen;     }     /**      * @brief 觸發(fā)事件      * @param string $event 事件      * @param mixed  $data  數(shù)據(jù)      * @notice 可以調(diào)用匿名函數(shù)和方法      */     public static function trigger($event,$data = null)     {         $result = array();         if(isset(self::$_listen[$event]))         {             foreach(self::$_listen[$event] as $key => $val)             {                 list($pluginObj,$pluginMethod) = $val;                 $result[$key] = is_callable($pluginObj) ? call_user_func($pluginObj,$data):call_user_func(array($pluginObj,$pluginMethod),$data);             }         }         return isset($result[1]) ? $result : current($result);     }     /**      * @brief 插件物理路徑      * @return string 路徑字符串      */     public static function path()     {         return IWeb::$app->getBasePath()."plugins/";     }     /**      * @brief 插件WEB路徑      * @return string 路徑字符串      */     public static function webPath()     {         return IUrl::creatUrl('')."plugins/";     }     /**      * @brief 獲取全部插件      * @param string $name 插件名字,如果為空則獲取全部插件信息      * @return array 插件信息 array(         "name"        => 插件名字,         "description" => 插件描述,         "explain"     => 使用說明,         "class_name"  => 插件ID,         "is_open"     => 是否開啟,         "is_install"  => 是否安裝,         "config_name" => 默認插件參數(shù)結(jié)構(gòu),         "config_param"=> 已經(jīng)保存的插件參數(shù),         "sort"        => 排序,      )      */     public static function getItems($name = '')     {         $result = array();         $dirRes = opendir(self::path());         //遍歷目錄讀取配置文件         $pluginDB = new IModel('plugin');         while($dir = readdir($dirRes))         {             if($dir[0] == "." || $dir[0] == "_")             {                 continue;             }             if($name && $result)             {                 break;             }             if($name && $dir != $name)             {                 continue;             }             $pluginIndex = self::path().$dir."/".$dir.".php";             if(is_file($pluginIndex))             {                 include_once($pluginIndex);                 if(get_parent_class($dir) == "pluginBase")                 {                     $class_name   = $dir;                     $pluginRow    = $pluginDB->getObj('class_name = "'.$class_name.'"');                     $is_open      = $pluginRow ? $pluginRow['is_open'] : 0;                     $is_install   = $pluginRow ? 1                     : 0;                     $sort         = $pluginRow ? $pluginRow['sort']    : 99;                     $config_param = array();                     if($pluginRow && $pluginRow['config_param'])                     {                         $config_param = JSON::decode($pluginRow['config_param']);                     }                     $result[$dir] = array(                         "name"        => $class_name::name(),                         "description" => $class_name::description(),                         "explain"     => $class_name::explain(),                         "class_name"  => $class_name,                         "is_open"     => $is_open,                         "is_install"  => $is_install,                         "config_name" => $class_name::configName(),                         "config_param"=> $config_param,                         "sort"        => $sort,                     );                 }             }         }         if(!$name)         {             return $result;         }         return isset($result[$name]) ? $result[$name] : array();     }     /**      * @brief 系統(tǒng)內(nèi)置的所有事件觸發(fā)      */     public static function onCreateApp(){plugin::init();plugin::trigger("onCreateApp");}     public static function onFinishApp(){plugin::trigger("onFinishApp");}     public static function onBeforeCreateController($ctrlId){plugin::trigger("onBeforeCreateController",$ctrlId);plugin::trigger("onBeforeCreateController@".$ctrlId);}     public static function onCreateController($ctrlObj){plugin::trigger("onCreateController");plugin::trigger("onCreateController@".$ctrlObj->getId());}     public static function onFinishController($ctrlObj){plugin::trigger("onFinishController");plugin::trigger("onFinishController@".$ctrlObj->getId());}     public static function onBeforeCreateAction($ctrlObj,$actionId){plugin::trigger("onBeforeCreateAction",$actionId);plugin::trigger("onBeforeCreateAction@".$ctrlObj->getId());plugin::trigger("onBeforeCreateAction@".$ctrlObj->getId()."@".$actionId);}     public static function onCreateAction($ctrlObj,$actionObj){plugin::trigger("onCreateAction");plugin::trigger("onCreateAction@".$ctrlObj->getId());plugin::trigger("onCreateAction@".$ctrlObj->getId()."@".$actionObj->getId());}     public static function onFinishAction($ctrlObj,$actionObj){plugin::trigger("onFinishAction");plugin::trigger("onFinishAction@".$ctrlObj->getId());plugin::trigger("onFinishAction@".$ctrlObj->getId()."@".$actionObj->getId());}     public static function onCreateView($ctrlObj,$actionObj){plugin::trigger("onCreateView");plugin::trigger("onCreateView@".$ctrlObj->getId());plugin::trigger("onCreateView@".$ctrlObj->getId()."@".$actionObj->getId());}     public static function onFinishView($ctrlObj,$actionObj){plugin::trigger("onFinishView");plugin::trigger("onFinishView@".$ctrlObj->getId());plugin::trigger("onFinishView@".$ctrlObj->getId()."@".$actionObj->getId());}     public static function onPhpShutDown(){plugin::trigger("onPhpShutDown");} } /**  * @brief 插件基類,所有插件必須繼承此類  * @notice 必須實現(xiàn)3個抽象方法: reg(),name(),description()  */ abstract class pluginBase extends IInterceptorBase {     //錯誤信息     protected $error = array();     //注冊事件接口,內(nèi)部通過調(diào)用payment::reg(事件,對象實例,方法);     public function reg(){}     /**      * @brief 默認插件參數(shù)信息,寫入到plugin表config_param字段      * @return array("字段名" => array(          "name"    => "文字顯示",          "type"    => "數(shù)據(jù)類型【text,radio,checkbox,select】",          "pattern" => "數(shù)據(jù)校驗【int,float,date,datetime,require,正則表達式】",          "value"   => "1,數(shù)組:枚舉數(shù)據(jù)【radio,checkbox,select】的預(yù)設(shè)值,array(名字=>數(shù)據(jù)); 2,字符串:【text】默認數(shù)據(jù)",         ))      */     public static function configName()     {         return array();     }     /**      * @brief 插件安裝      * @return boolean      */     public static function install()     {         return true;     }     /**      * @brief 插件卸載      * @return boolean      */     public static function uninstall()     {         return true;     }     /**      * @brief 插件名字      * @return string      */     public static function name()     {         return "插件名稱";     }     /**      * @brief 插件功能描述      * @return string      */     public static function description()     {         return "插件描述";     }     /**      * @brief 插件使用說明      * @return string      */     public static function explain()     {         return "";     }     /**      * @brief 獲取DB中錄入的配置參數(shù)      * @return array      */     public function config()     {         $className= get_class($this);         $pluginDB = new IModel('plugin');         $dataRow  = $pluginDB->getObj('class_name = "'.$className.'"');         if($dataRow && $dataRow['config_param'])         {             return JSON::decode($dataRow['config_param']);         }         return array();     }     /**      * @brief 返回錯誤信息      * @return array      */     public function getError()     {         return $this->error ? join("rn",$this->error) : "";     }     /**      * @brief 寫入錯誤信息      * @return array      */     public function setError($error)     {         $this->error[] = $error;     }     /**      * @brief 插件視圖渲染有布局      * @param string $view 視圖名字      * @param array  $data 視圖里面的數(shù)據(jù)      */     public function redirect($view,$data = array())     {         if($data === true)         {             $this->controller()->redirect($view);         }         else         {             $__className      = get_class($this);             $__pluginViewPath = plugin::path().$__className."/".$view;             $result = self::controller()->render($__pluginViewPath,$data);             if($result === false)             {                 IError::show($__className."/".$view."插件視圖不存在");             }         }     }     /**      * @brief 插件視圖渲染去掉布局      * @param string $view 視圖名字      * @param array  $data 視圖里面的數(shù)據(jù)      */     public function view($view,$data = array())     {         self::controller()->layout = "";         $this->redirect($view,$data);     }     /**      * @brief 插件物理目錄      * @param string 插件路徑地址      */     public function path()     {         return plugin::path().get_class($this)."/";     }     /**      * @brief 插件WEB目錄      * @param string 插件路徑地址      */     public function webPath()     {         return plugin::webPath().get_class($this)."/";     } }

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號