CI フレームワークのソースコード閲覧メモ 6 拡張フック Hook.php、cihook.php_PHP チュートリアル

WBOY
リリース: 2016-07-13 10:14:50
オリジナル
883 人が閲覧しました

CI フレームワークのソースコード読み取りメモ 6 拡張フック Hook.php、cihook.php

CI フレームワークを使用すると、システムのコア機能 (キャッシュの書き換え、出力など) を変更せずに追加または変更できます。システムのコアコード。たとえば、システム (config.php の $config['enable_hooks'] = TRUE;) でフックが有効になっている場合、特定のフックを追加することで、システムは特定の時間に特定のスクリプトをトリガーできます。 リーリー

上記のフックは、最終ページがレンダリングされた後のスクリプト処理に使用される post_system フックを定義します (パラメータの意味は後ほどまたはマニュアルで参照でき、ここではこれ以上の説明は行いません)。

そして次の質問が来ます:

段階的に見てみましょう。

1.

フックとは

Baidu百科事典におけるフックの定義は次の通りです:

リーリー

上記の定義からいくつかの点がわかります:

2. CI の事前定義フック

CI は、次の 7 つの利用可能なプリセット フック ポイントを提供します:

pre_system: システムロードの初期段階のフックを指します

pre_controller: コントローラーを呼び出す前のフック、ルーティング、セキュリティチェックが完了しました

post_controller_constructor: コントローラーがインスタンス化された後、メソッドが呼び出される前

post_controller: コントローラーが完全に実行された後

display_override: 表示を書き換えます

cache_override:キャッシュを書き換える

post_system: 最終ページがクライアントに送信された後

3. CI でのフックの実装

CI におけるフックのコア機能は、Hook コンポーネントによって完成します。まず、このコンポーネントのクラス図を見てみましょう。

その中に:

enabled

:フック機能が有効かどうかを示すフラグ。

フック

: システムで有効になっているフックのリストを保存します

in_progress

: このフラグはフック間の相互呼び出しによって引き起こされる無限ループを防ぐために使用されることが後でわかります。

_construct

はHookコンポーネントのコンストラクターであり、_initializeが呼び出されて初期化作業が完了します

_call_hook

: _run_hookを呼び出して、指定されたフックプログラムを呼び出します。 CodeIgniter.php で、_call_hook が実際に外部呼び出しに提供されるインターフェイスであることを以前に見てきました。

_run_hook

:フックプログラムを実際に実行する関数

始める前に、事前定義されたフックの構造を投稿しましょう。この構造はソース コード全体に現れる可能性があるため、この構造のパラメータの意味を知る必要があります。

リーリー

1.フックコンポーネントの初期化

_initialize 関数はフックコンポーネントを初期化するために使用されます。この関数の主なタスクは次のとおりです。

(1) Config(構成管理コンポーネント)のロードが必要な構成ファイル内のフック機能が有効になっているかどうかを確認します:

リーリー

(2) 定義されたフックリストをロードします

同様に、異なるフックを有効にするために異なる ENVIRONMENT を設定することもできます。ある場合は、

ENVRIONMENT の下のフックが最初にロードされます:

。 リーリー

(3)フックチェック。フックが設定されていない場合、またはフックの形式が間違っている場合は、処理は行われず、直接終了します: リーリー

初期化後、定義されたフックリストは Hook::hooks: に保存されます

リーリー

2. 指定されたフックを呼び出す

_call_hookはメインプログラム内で直接呼び出されるインターフェースです。このインターフェースの主なタスクは次のとおりです:

(1). フックが有効かどうか、および呼び出しフックが事前定義されているかどうかを確認します (有効になっていない場合、または呼び出しフックが存在しない場合は、直接戻ります)。 リーリー (2). 同じフックポイントで複数のフックが有効になっているかどうかを確認し、有効になっている場合は、それらを順番に実行します。 リーリー

(3)。そうでない場合は、フックが 1 つしかないので、それを実行します

リーリー

_run_hookは実際にフックを実行する関数です。

3. 特定のフックプログラムを実行するために実行します

_run_hook

関数は、フックの実際の実行者であり、事前定義されたフック配列をパラメータとして受け取り、次のように実装されます。

(1)。渡されたパラメータがまったく配列ではない場合 (当然、有効なフックではありません)、直接戻ります:

if ( ! is_array($data))
{
	return FALSE;
}
ログイン後にコピー

(2). 检查hook执行状态。

in_progress用于标志当前hook的执行状态。这个参数的主要作用,是防止hook之间的相互调用而导致的死循环。

if ($this->in_progress == TRUE)
{
	return;
}
ログイン後にコピー

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

为了方便讲述,我们再次提出一个预定义的hook需要的参数:

<span>$hook</span>['xx'] = <span>array</span><span>(
    </span>'class'     => 'xx', <span>//</span><span>钩子调用的类名,可以为空</span>
    'function'  => 'xx',<span>//</span><span>钩子调用的函数名</span>
    'filename'  => 'xx',<span>//</span><span>该钩子的文件名</span>
    'filepath'   => 'xx',<span>//</span><span>钩子的目录</span>
    'params'   => 'xx'<span>//</span><span>传递给钩子的参数</span>
);
ログイン後にコピー

其中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;
	}

}
ログイン後にコピー

参考文献

1.  http://codeigniter.org.cn/user_guide/general/hooks.html   手册

2.  http://itopic.org/codeigniter-hook.html  

3.  http://codeigniter.org.cn/forums/thread-4947-1-1.html  钩子实现的Layout

CI框架引入模板问题

这个……好像CI没啥方法,倒是可以通过写模板的时候include进去header.php和footer.php,倒是还有听说smarty模板引擎中有模板继承这个概念,可以让你的内容页继承某个页面,那个页面上写着header.php和footer.php,貌似CI是可以使用smarty模板引擎的,不过我没有那样用过,还有,CI有hook(钩子)这个东西,老实说我没用过,不知道它能不能实现。
 

CI框架 怎实现统计网站点击量,哪位把源码发我跪

是记录有多少人进去你的网站还是说点击的某个连接多少次?
 

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/908124.htmlTechArticleCI框架源码阅读笔记6 扩展钩子 Hook.php,cihook.php CI框架允许你在不修改系统核心代码的基础上添加或者更改系统的核心功能(如重写缓存、...

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート