亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > PHP > 正文

CI框架源碼閱讀筆記6 擴展鉤子 Hook.php

2020-03-22 20:26:22
字體:
來源:轉載
供稿:網友
  •   CI框架允許你在不修改系統核心代碼的基礎上添加或者更改系統的核心功能(如重寫緩存、輸出等)。例如,在系統開啟hook的條件下(config.php中$config['enable_hooks'] = TRUE;),通過添加特定的鉤子,可以讓系統在特定的時刻觸發特定的腳本:

    $hook['post_system'] = array(    'html' target='_blank'>class'     => 'frameLog',    'function'  => 'postLog',    'filename'  => 'post_system.php',    'filepath'   => 'hooks',);

    上述鉤子定義了一個post_system的鉤子,用于在最終的頁面渲染之后的腳本處理(參數的含義可以參考后面或者手冊,這里暫時不做更多解釋)。

    那么問題來了:

    鉤子是什么? CI中支持的鉤子有哪些? CI中鉤子是如何實現的?

    我們一步步來看。

    1.  鉤子是什么

      百度百科上對于鉤子的定義是:

    鉤子實際上是一個處理消息的程序段,通過系統調用,把它掛入系統。每當特定的消息發出,在沒有到達目的窗口前,鉤子程序就先捕獲該消息,亦即鉤子函數先得到控制權。這時鉤子函數即可以加工處理(改變)該消息,也可以不作處理而繼續傳遞該消息,還可以強制結束消息的傳遞。

      從上述定義我們可以看出幾點:

    鉤子是一種事件驅動模式,它的核心自然是事件(CI中pre_system,pre_controller等都是特定的事件)。 既然是事件驅動,那么必然要包含最重要的兩個步驟: (1)、事件注冊。對于Hook而言,就是指Hook鉤子的掛載。(2).事件觸發。在特定的時間點call特定的鉤子,執行相應的鉤子程序。 既然是事件驅動,那么也應該支持統一掛鉤點的多個注冊事件。 啟動Hook鉤子之后,程序的流程可能會發生變化,且鉤子之間可能有相互調用的可能性,如果處理不當,會有死循環的可能性。同時,鉤子的啟用使得程序在一定程度上變得復雜,難以調試。2.  CI中預定義鉤子

    CI中提供了7個可用的預設掛鉤點,分別是:

      pre_system: 指在系統加載前期的鉤子

      pre_controller:調用控制器之前的鉤子,路由與安全性檢查已經完畢

      post_controller_constructor:控制器實例化之后,任何方法調用之前

      post_controller:控制器完全運行之后

      display_override:重寫display

      cache_override :重寫緩存

      post_system:最終的頁面發送到客戶端之后

    3.  CI中鉤子的實現

      CI中鉤子的核心功能是由Hook組件完成的,先看該組件的類圖:

    其中:

      enabled: 鉤子功能是否開啟的標志。

      hooks :保存系統中啟用的鉤子列表

      in_progress:之后我們會看到,這個標志位用于防止鉤子之間的互相調用而導致的死循環。

      _construct是Hook組件的構造函數,這其中調用了_initialize來完成初始化的工作

      _call_hook: 調用_run_hook來call指定的鉤子程序。之前CodeIgniter.php中我們已經看到,_call_hook是實際提供給外部調用的接口。

      _run_hook: 實際執行鉤子程序的函數

    在開始之前,我們先貼出預定義鉤子的結構。這個結構可能會貫穿在源代碼的始終,因而我們有必要知道該結構的參數含義。

    $hook['xx'] = array(    'class'     => 'xx', //鉤子調用的類名,可以為空    'function'  => 'xx',//鉤子調用的函數名    'filename'  => 'xx',//該鉤子的文件名    'filepath'   => 'xx',//鉤子的目錄    'params'   => 'xx'//傳遞給鉤子的參數);

    1.  鉤子組件初始化

    _initialize函數用于鉤子組件的初始化,該函數主要完成的工作有:

    (1) 檢查配置文件中hook功能是否被啟用,這需要加載Config(配置管理組件):

    $CFG =& load_class('Config', 'core');if ($CFG->item('enable_hooks') == FALSE){	return;}

    (2) 加載定義的hook列表

    同樣,你可以設定不同的ENVIRONMENT啟用不同的hook,如果有的話,優先加載ENVRIONMENT下的hook:

    if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/hooks.php')){    include(APPPATH.'config/'.ENVIRONMENT.'/hooks.php');}elseif (is_file(APPPATH.'config/hooks.php')){	include(APPPATH.'config/hooks.php');}

    (3) Hook的檢查。如果未設置任何hook,或者設置的hook格式錯誤,則不作任何處理,直接退出:

    if ( ! isset($hook) OR ! is_array($hook)){	return;}

    經過initialize之后,Hook::hooks中存儲了已經定義的hook列表:

    $this->hooks =& $hook;

    2.  Call指定的鉤子

    _call_hook是主程序中直接調用的接口。該接口主要的工作有:

    (1). 檢查鉤子是否被啟用,以及call的鉤子是否被預定義(如果未啟用或者call的鉤子不存在,則直接返回):

    if ( ! $this->enabled OR ! isset($this->hooks[$which])){	return FALSE;}

    (2). 檢查同一個掛鉤點是否啟用了多個鉤子,如果有,則依次執行之:

    if (isset($this->hooks[$which][0]) AND is_array($this->hooks[$which][0])){	foreach ($this->hooks[$which] as $val)	{		$this->_run_hook($val);	}}

    (3). 否則,只有一個鉤子,執行它

    else{	$this->_run_hook($this->hooks[$which]);}

    _run_hook是實際執行hook的函數。

    3.  run執行特定的鉤子程序

    _run_hook函數是hook的實際執行者,該函數接收一個預定義的hook數組作為參數,實現如下:

    (1). 如果傳遞的參數壓根就不是數組(自然也就不是有效的hook),那么直接返回:

    if ( ! is_array($data)){	return FALSE;}

    (2). 檢查hook執行狀態。

    in_progress用于標志當前hook的執行狀態。這個參數的主要作用,是防止hook之間的相互調用而導致的死循環。

    if ($this->in_progress == TRUE){	return;}

    (3). Hook的合法性檢查。

    為了方便講述,我們再次提出一個預定義的hook需要的參數:

    $hook['xx'] = array(    'class'     => 'xx', //鉤子調用的類名,可以為空    'function'  => 'xx',//鉤子調用的函數名    'filename'  => 'xx',//該鉤子的文件名    'filepath'   => 'xx',//鉤子的目錄    'params'   => 'xx'//傳遞給鉤子的參數);

    其中class和params是可選參數,其他3個參數為必選參數,如果不提供,則由于無法準確定位到hook程序,只能直接返回:

    if ( ! isset($data['filepath']) OR ! isset($data['filename'])){	return FALSE;}$filepath = APPPATH.$data['filepath'].'/'.$data['filename'];if ( ! file_exists($filepath)){	return FALSE;}

    (4). 到這里,已經基本確認鉤子程序的位置了,這里有兩種情況:

    a. 預定義的hook中class參數為空,表明使用的是過程式的調用方式,則直接執行hook文件中的function xxx

    b. class參數不為空,提供的是面向對象的方式,則實際的鉤子程序是$class->$function .同樣,如果既沒有設置class,也沒有設置function參數,則無法執行hook,直接返回:

    $class		= FALSE;$function	= FALSE;$params		= '';/* 獲取 hook class */if (isset($data['class']) AND $data['class'] != ''){	$class = $data['class'];}/* 獲取 hook function */if (isset($data['function'])){	$function = $data['function'];}/* 獲取傳遞的 hook 參數 */if (isset($data['params'])){	$params = $data['params'];}/* 如果class和function都不存在,則無法定位hook程序,直接返回 */if ($class === FALSE AND $function === FALSE){	return FALSE;}

    (5). 設置執行標志in_progress,并執行上述兩種情況下的hook:

    /* 面向對象的設置方式 */if ($class !== FALSE){	if ( ! class_exists($class))	{		require($filepath);	}	$HOOK = new $class;	$HOOK->$function($params);}/*  過程式的執行方式 */else{	if ( ! function_exists($function))	{		require($filepath);	}	$function($params);}

    最后,別忘了在hook執行完之后,設置標識位in_progress為false,并返回執行成功的標志:

    $this->in_progress = FALSE;return TRUE;

    Hook組件的完整源碼:

    <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');class CI_Hooks {	/**	 * Determines wether hooks are enabled	 *	 * @var bool	 */	var $enabled		= FALSE;	/**	 * List of all hooks set in config/hooks.php	 *	 */	var $hooks			= array();	/**	 * Determines wether hook is in progress, used to prevent infinte loops	 *	 */	var $in_progress	= FALSE;	/**	 * Constructor	 */	function __construct()	{		$this->_initialize();		log_message('debug', 'Hooks Class Initialized');	}	/**	 * Initialize the Hooks Preferences	 *	 * @access	private	 * @return	void	 */	function _initialize()	{		$CFG =& load_class('Config', 'core');		// If hooks are not enabled in the config file		// there is nothing else to do		if ($CFG->item('enable_hooks') == FALSE)		{			return;		}		if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/hooks.php'))		{		    include(APPPATH.'config/'.ENVIRONMENT.'/hooks.php');		}		elseif (is_file(APPPATH.'config/hooks.php'))		{			include(APPPATH.'config/hooks.php');		}		if ( ! isset($hook) OR ! is_array($hook))		{			return;		}		$this->hooks =& $hook;		$this->enabled = TRUE;	}	/**	 * Call Hook	 *	 * Calls a particular hook	 *	 * @access	private	 * @param	string	the hook name	 * @return	mixed	 */	function _call_hook($which = '')	{		if ( ! $this->enabled OR ! isset($this->hooks[$which]))		{			return FALSE;		}		if (isset($this->hooks[$which][0]) AND is_array($this->hooks[$which][0]))		{			foreach ($this->hooks[$which] as $val)			{				$this->_run_hook($val);			}		}		else		{			$this->_run_hook($this->hooks[$which]);		}		return TRUE;	}	/**	 * Run Hook	 *	 * Runs a particular hook	 *	 * @access	private	 * @param	array	the hook details	 * @return	bool	 */	function _run_hook($data)	{		if ( ! is_array($data))		{			return FALSE;		}		// If the script being called happens to have the same hook call within it a loop can happen		if ($this->in_progress == TRUE)		{			return;		}		if ( ! isset($data['filepath']) OR ! isset($data['filename']))		{			return FALSE;		}		$filepath = APPPATH.$data['filepath'].'/'.$data['filename'];		if ( ! file_exists($filepath))		{			return FALSE;		}		$class		= FALSE;		$function	= FALSE;		$params		= '';		if (isset($data['class']) AND $data['class'] != '')		{			$class = $data['class'];		}		if (isset($data['function']))		{			$function = $data['function'];		}		if (isset($data['params']))		{			$params = $data['params'];		}		if ($class === FALSE AND $function === FALSE)		{			return FALSE;		}		$this->in_progress = TRUE;		// Call the requested class and/or function		if ($class !== FALSE)		{			if ( ! class_exists($class))			{				require($filepath);			}			$HOOK = new $class;			$HOOK->$function($params);		}		else		{			if ( ! function_exists($function))			{				require($filepath);			}			$function($params);		}		$this->in_progress = FALSE;		return TRUE;	}}
    PHP編程

    鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。

  • 發表評論 共有條評論
    用戶名: 密碼:
    驗證碼: 匿名發表
    亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
    精品久久在线播放| 亚洲男人的天堂在线播放| 日韩精品在线观看一区| 亚洲色图美腿丝袜| 亚洲精品国产suv| 中文日韩在线视频| 色偷偷综合社区| 在线国产精品播放| 国产视频精品在线| 亚洲免费电影在线观看| 性色av一区二区三区在线观看| 久久电影一区二区| 欧美成在线视频| 精品动漫一区二区三区| 91精品国产高清久久久久久| 一区二区欧美在线| 亚洲精品98久久久久久中文字幕| 色噜噜亚洲精品中文字幕| 欧美猛交ⅹxxx乱大交视频| 国产91色在线免费| 亚洲最大av在线| 日韩av一区在线| 国产精品成人va在线观看| 国产91|九色| 日韩欧美精品在线观看| 国产91成人在在线播放| 欧美肥老太性生活视频| 欧美韩日一区二区| 日本成人激情视频| 97精品欧美一区二区三区| 国内自拍欧美激情| 欧美黑人巨大精品一区二区| 欧美精品在线视频观看| 一区二区三区无码高清视频| 伊人久久免费视频| 国产精品视频不卡| 欧洲美女免费图片一区| 亚洲第一综合天堂另类专| 国产精品91久久久久久| 亚洲欧美国产精品专区久久| 亚洲已满18点击进入在线看片| 欧美激情图片区| 日韩成人久久久| 国产亚洲美女精品久久久| 亚洲欧美成人网| 中文字幕亚洲二区| 国产成人精品一区二区| 亚洲四色影视在线观看| 国产精品成人va在线观看| 成人中文字幕+乱码+中文字幕| 亚洲精选一区二区| 亚洲精品免费av| 久久综合免费视频影院| 日韩在线精品一区| 中文字幕视频一区二区在线有码| 麻豆国产va免费精品高清在线| 成人福利在线观看| 成人在线观看视频网站| 久久全球大尺度高清视频| 国产精品久久久久久久久久久新郎| 一区二区三区日韩在线| 91精品国产综合久久香蕉922| 96pao国产成视频永久免费| 中文字幕亚洲一区| 欧美一级成年大片在线观看| 欧美日本啪啪无遮挡网站| 国产精品狼人色视频一区| 在线播放精品一区二区三区| 久久久久久久久久久91| 日本精品视频在线| 日韩精品视频三区| 2019国产精品自在线拍国产不卡| 国外成人免费在线播放| 日韩a**站在线观看| 97成人精品视频在线观看| 福利一区福利二区微拍刺激| 国产91成人video| 国产中文字幕日韩| 国产中文字幕亚洲| 久久精品视频va| 欧美一级电影久久| 国产成人精品一区二区三区| 亚洲第五色综合网| 国产精品观看在线亚洲人成网| 欧美日韩在线另类| 亚洲激情第一页| 欧美日韩国产成人在线| xxx成人少妇69| 欧美性xxxx极品hd欧美风情| 久久久久www| 成人网在线免费看| 国产亚洲美女久久| 日韩精品视频在线观看免费| 亚洲欧美精品一区| 欧美肥婆姓交大片| 日韩电影中文字幕在线观看| 日韩在线播放视频| 精品一区电影国产| 热久久99这里有精品| 久热在线中文字幕色999舞| 国产精品美女主播| 午夜精品久久久久久久白皮肤| 亚洲精品资源美女情侣酒店| 欧美国产中文字幕| 欧美精品亚州精品| 国产精品91免费在线| 亚洲精品mp4| 欧美在线视频播放| 亚洲欧美国产高清va在线播| 欧美成人剧情片在线观看| 欧美影院成年免费版| 日韩一中文字幕| 亚洲а∨天堂久久精品9966| 岛国av午夜精品| 国产精品欧美一区二区三区奶水| 国产精品1234| 一区二区三区精品99久久| 亚洲va欧美va在线观看| 久久中文字幕在线视频| 亚洲图片欧美日产| 国产丝袜精品视频| 亚洲精品久久久一区二区三区| 欧美激情中文字幕乱码免费| 高清欧美性猛交xxxx黑人猛交| 91精品国产九九九久久久亚洲| 国产精品嫩草视频| 国产一区二区久久精品| 国产a∨精品一区二区三区不卡| 亚洲成人久久久| 国产丝袜一区二区三区| 在线不卡国产精品| 国产精品视频精品| 欧美在线一级va免费观看| 亚洲成人久久久| 亚洲已满18点击进入在线看片| 国产在线观看不卡| 日韩欧美国产网站| zzjj国产精品一区二区| 欧洲永久精品大片ww免费漫画| 亚洲人线精品午夜| 91欧美激情另类亚洲| 精品国产电影一区| 国产日本欧美在线观看| 亚洲一区二区三区久久| 国产精品网红福利| 色综合久综合久久综合久鬼88| 国产精品青青在线观看爽香蕉| 亚洲精品美女久久| 456亚洲影院| 国产69精品久久久| 国产亚洲欧美另类中文| 夜色77av精品影院| 久久久久免费精品国产| 久久99青青精品免费观看| 欧美大尺度电影在线观看| 国产亚洲一区精品| 国产精品欧美风情| 国产精品高潮呻吟视频| 久久久国产91| 2024亚洲男人天堂| 日韩在线视频免费观看高清中文| 日本一区二区在线免费播放| 日本国产欧美一区二区三区| 日韩欧亚中文在线|