国产激情自拍_国产9色视频_丁香花在线电影小说观看 _久久久久国产精品嫩草影院

首頁 > 編程 > 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編程

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

  • 發表評論 共有條評論
    用戶名: 密碼:
    驗證碼: 匿名發表
    国产激情自拍_国产9色视频_丁香花在线电影小说观看 _久久久久国产精品嫩草影院
    97视频网站| 天天操天天操一操| 国产精品亚洲第五区在线| 激情四房婷婷| 国产麻豆精品视频一区二区| 国产鲁鲁视频在线观看特色| 国产在线观看91| 天堂在线免费av| 激情丁香在线| 国产一级视频| 精品一区二区三区在线成人| 亚洲免费网站在线观看| 激情视频国产| 国产成人午夜电影| 人人澡人人爽| 国产精品jvid在线观看| 在线国产1区| 成年人在线观看| 精品国内自产拍在线视频| 蜜桃视频中文字幕| 国产成人精品18| 色悠久久久久综合网小说| 国产毛片毛片毛片| 中文字幕av在线播放| 美女免费视频黄| 精品国产福利一区二区在线| 激情四房婷婷| 青青草视频免费在线观看| 中文字幕不卡免费视频| 青青草免费在线观看| 在线一区观看| 国产a级网站| 国产精品第八页| 尤物网站在线| 国产中文字幕在线播放| 色吊丝av中文字幕| 亚洲综合在线网| 精品国产一区二区三区不卡在线| 国产视频精品久久| 国产专区在线| 免费看av大片| 超碰免费在线| 久艹在线视频| 成人免费一区二区三区牛牛 | 国产免费专区| 啪啪免费视频一区| 超碰免费在线播放| 九九热在线观看| 国产尤物视频在线| 五月天天在线| 国产福利资源| 69视频在线观看| 精品国内自产拍在线视频| 国产porny蝌蚪视频| 精品美女调教视频| 日本不卡影院| 国产一二三区精品视频| 国产福利片在线| 亚洲最新永久观看在线| 免费看成年人视频在线观看| 国产女人在线观看| 国产成人夜间影院在线观看| 亚洲综合色视频在线观看| 国产中文第一页| 国产激情视频一区二区三区| 99中文字幕一区| 欧美96在线| 国产网红在线| 日本h视频在线观看| 中文字幕在线观看日本| 91麻豆免费在线视频| av在线你懂的| 国产亚洲精品午夜高清影院| 在线亚洲精品自拍| 国产免费av在线| 亚洲综合激情六月婷婷在线观看| 九九热视频免费在线观看| 国产一卡二卡3卡4卡四卡在线| 91看片在线观看| 综合激情丁香| 日本福利在线观看| 国产精品xxx电影| 国产永久在线观看| 99热99re6国产在线播放| 狠狠色综合久久婷婷| 在线播放一区二区精品产| 国产一二三视频| 久草亚洲一区| 日本黄色免费网址| 在线观看av的网站| 99久久国产视频| 精品国产二区三区| 在线午夜视频| 国产91在线视频蝌蚪| 中文字幕一区免费| 日本中文字幕在线播放| sese在线视频| 亚洲免费网站在线观看| 91久久精品国产性色| 国产精品入口麻豆免费看| 国产精品一区二区资源| 国自产拍在线网站网址视频| 欧美性猛交xxxx免费看久久| av日韩国产| av在线电影观看| 亚洲精品视频区| 夜夜操com| 在线观看免费黄色| 亚洲电影视频在线| 日本视频一二三区中文字幕| 日日夜夜中文字幕| a视频免费看| 亚洲wwwwww| 亚洲精品成人a| 九九99精品| 国产精品毛片一区二区三区四区| 国产私拍精品| 精品国语对白精品自拍视| 精品麻豆视频| gogo在线高清视频| 九九在线视频| 国产偷激情在线| 99reav| 日本在线天堂| 国产精品美女一区二区视频| 精品卡一卡卡2卡3网站| 在线观看的av网站| 成人精品一区二区三区免费| 国产激情网址| 久久精品国产亚洲a∨麻豆| 中文字幕在线看精品乱码| 69av二区| 国产乱精品一区二区三区| 国产黄在线观看免费观看不卡| www.中文字幕久久久| 国产午夜电影| 免费a在线看| 精品176二区| 五月婷婷在线观看| 欧美成人久久电影香蕉| 国产成人精品18| 开心婷婷激情五月| 中文乱码字幕av网站| 激情小说 在线视频| 99在线视频观看| 国产一起色一起爱| 欧美性猛交p30| 一本免费视频| 国产www视频在线观看| 天堂在线视频| 丁香花在线电影小说观看 | 高潮毛片在线观看| 在线视频婷婷| 精品国内自产拍在线视频| 欧美韩日国产| 四虎成人欧美精品在永久在线| 国产午夜在线| 中文字幕国产视频| 国产蜜臀av在线播放| 久热中文字幕在线观看| 欧美日韩亚洲国内综合网| 日本三级在线视频| 日本高清中文字幕在线| www.五月色.com| 欧美日韩性视频一区二区三区| 伊人av免费在线观看| 在线视频xx| 青青艹在线视频| 激情在线视频播放| 欧美成人久久电影香蕉| 日本电影全部在线观看网站视频| 亚洲精品xxxxx| 操人视频91| 99热在线免费观看| 国产馆av播放| av中文字幕在线看| 青青国产在线| 国产卡一卡二卡三| 国产精品第八页| 在线免费国产| 久热中文字幕精品视频在线| 九九色在线观看| 国产精品四虎| 永久免费av片在线观看全网站| 精品乱码一区二区三四区视频| 99热免费在线观看| 粉嫩av一区| 精品国产二区三区| 美女永久在线网站| 中文字幕在线第一页| 中文资源在线网| 国产在线你懂得| 中文字幕2019第三页| 国产免费av高清在线| 在线āv视频| 在线91av| 久久久久久久美女| av网站在线播放| 午夜国产在线| eeuss影院在线观看第一页|