php鈎子程序設計


 
  
  作為程序員,設計出優雅而完美的系統,永遠是讓我們非常興奮的事情。高手不在於你會多少語言,而在於你有多高的思想。
 
  在設計中,怎么體現自身價值,那就是要比別人多想幾步。
 
  講鈎子程序,起源是對用戶提交的參數校驗(永遠不要相信用戶),一開始為了趕工期,按照比較傳統的方式,每個接口里重復性的對參數進行過濾。后面隨着業務的發展(功能迭代),系統的維護成本越來越高,遂想一個更高級的方式進行處理。借鑒同事之前的代碼,使用鈎子方式進行重構。
 
  之前寫過javascript 鈎子機制, 偏后鈎,可以互相借鑒下。
 
脈路
  
 
 
 
概念
  
  把一段程序塊(執行體)通過某種方式掛入系統中,從而獲得對系統的控制權。
 
       注意下圖掛鈎位置:
 

 

 
 
應用
  
  小的方面: 進行基礎的入參校驗或消息過濾。
  大的方面:組件化,可在系統中進行插拔管理。
  
  優點:
    1、降低系統的耦合度;
    2、降低開發、測試人力成本,用少量的代碼實現高可用功能;
    3、提高模塊間的可用性;
    4、通過配置(配置文件or數據庫)的方式升級接口。
  缺點:
    學習成本過高;
    系統復雜度提升;
 

 
實現思想
  
 
     配置文件的方式進行鈎子定義、鈎子鏈管理(使用“組”的概念)、掛鈎。
 
  

 

    鈎子:程序執行體;
      鈎子組: 鈎子鏈的分類定義;
           掛鈎: 入口(MVC中action或者controller)與鈎子組進行綁定。
 
 

 
實現方式
  
   
 
  
       掛鈎器(繼承類):
<?php
/**
 * @name Service_Page_Test
 * @desc page層對接第三方抽象類
 * @author  
 */
abstract class Service_Page_Test 
{
	public $hookGroupPrev = null; // 前鈎子組
	public $hookGroupAfter = null; // 后鈎子組
	public $hookReturn = array(); //鈎子返回值
	public $reqData = null; // page模塊分析的數據

    /**
     * 獲取需要驗證的參數配置
     * @return array
     */
    public function _getCheckParams()
    {
        return array();
    }



    /**
	 * 入口方法
     * @param array $arrInput
     * @return array
     */
    public function execute($arrInput)
    {
        $res = array(
            'errno' => Test_Errno::ERRNO_SUCCESS,
            'errmsg' => Test_Errno::$ERRMSG[Test_Errno::ERRNO_SUCCESS],
        );
        try {
            $this->_init($arrInput);
            $this->_beforeExecute();
            $res = $this->doExecute($arrInput);
            $this->_afterExecute();
        } catch (Test_Exception $e) { 
            $res = array(
                'errno' => $e->getCode(),
                'errmsg' => $e->getMessage(),
            );
	    } catch (Exception $e) {
            $res = array(
                'errno' => $e->getCode(),
                'errmsg' => $e->getMessage(),
            );

        }
        return $res;
    }



	/**
     * auto exec 
     * @param array $arrInput
     * @throws Exception
     * @return array
     */
	protected function doExecute($arrInput){
	}


    /**
     * 獲取權限信息
     * @param array $arrInput
     * @return array
     */
    public function _init($arrInput)
    {
        $pageModulesConf = Conf::getConf('page/' . get_class($this));
        $this->reqData = $arrInput;
		$this->hookGroupPrev[] = $pageModulesConf['hook_group']['prev'];
		$this->hookGroupAfter[] = $pageModulesConf['hook_group']['after'];
	}


    /**
     * 執行filter
     * @param string 
     */
    public function _beforeExecute()
    {
        if (!empty($this->hookGroupPrev) && is_array($this->hookGroupPrev)) {
            foreach ($this->hookGroupPrev as $hookGroups) {
                foreach ($hookGroups as $hookGroup) {
                    $this->_executeHook($hookGroup, $this->reqData);
                }
            }
        }
    }


    /**
     * @param array $arrInput
     * @return array
     */
    public function _afterExecute()
    {
        if (!empty($this->hookGroupAfter) && is_array($this->hookGroupAfter)) {
            foreach ($this->hookGroupAfter as $hookGroups) {
				foreach ($hookGroups as $hookGroup) {
					$this->_executeHook($hookGroup, $this->reqData);
				}
            }
        }
    }


    /**
     * 執行filter
     * @param string
     */
    public function _executeHook($hookGroup, $reqData)
    {

        $hookGroupConf = Conf::getConf('hook/group/' . $hookGroup);
		if(!empty($hookGroupConf)){
			foreach($hookGroupConf as $hook){
				$hookConf = Conf::getConf('hook/hook/' . $hook);
				$class = $hookConf['class'];
				$method = $hookConf['method'];
				$inputParams = isset($hookConf['getInputParams']) ? $this->{$hookConf['getInputParams']}() : null;
				if (class_exists($class)) {
					$obj = new $class();
					if (method_exists($obj, $method)) {
						$this->hookReturn[$hook][] =  $obj->$method($inputParams, $reqData);
					}
				}
			}
		}

    }

}

  

 

  hook.conf

# 鈎子組
[group] [.check_req_customer]
0 : checkReqCustomerBaseInfo [.after_demo] 0 : afterDemo # 鈎子 [hook] [.checkReqCustomerBaseInfo] class: Service_Page_Hook_Customer method: checkBaseInfo getInputParams: _getCheckParams [.afterDemo] class: Service_Page_Hook_Customer method: afterDemo getInputParams: _getCheckParams

 

  page.conf
[Service_Page_Input]
#綁定鈎子組
[.hook_group]
[..prev]
0 : check_req_customer
[..after]
0 : after_demo

  

 
 
 
推薦
 
 
 
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM