欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  后端开发

codeigniter是如何实现钩子机制的?

程序员文章站 2022-05-01 12:21:02
...

codeigniter是如何实现钩子机制的?,有需要的朋友可以参考下。


记得上一次去到喜啦面试,面试官问我一个问题:codeigniter是如何实现钩子机制的?
当时答不上来,后来回来之后查了一些资料才明白,所以在这里记录一下:
codeigniter的钩子是这样实现的:首先在框架的核心文件system/core/CodeIniter.php文件的 122行,载入Hooks类,接着在该文件中定义了几个挂载点,比如pre_system(129行)、post_controller_constructor(295行)等,并在这些挂载点上面执行hooks类的_call_hook() 方法。

另附codeigniter的hooks类的源代码:

  1. /**
  2. * CodeIgniter
  3. *
  4. * An open source application development framework for PHP 5.1.6 or newer
  5. *
  6. * @package CodeIgniter
  7. * @author EllisLab Dev Team
  8. * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
  9. * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
  10. * @license http://codeigniter.com/user_guide/license.html
  11. * [url=home.php?mod=space&uid=17823]@LINK[/url] http://codeigniter.com
  12. * @since Version 1.0
  13. * @filesource
  14. */
  15. // ------------------------------------------------------------------------
  16. /**
  17. * CodeIgniter Hooks Class
  18. *
  19. * Provides a mechanism to extend the base system without hacking.
  20. *
  21. * @package CodeIgniter
  22. * @subpackage Libraries
  23. * @category Libraries
  24. * @author EllisLab Dev Team
  25. * @link http://codeigniter.com/user_guide/libraries/encryption.html
  26. */
  27. class CI_Hooks {
  28. /**
  29. * Determines wether hooks are enabled
  30. *
  31. * @var bool
  32. */
  33. var $enabled = FALSE;
  34. /**
  35. * List of all hooks set in config/hooks.php
  36. *
  37. * @var array
  38. */
  39. var $hooks = array();
  40. /**
  41. * Determines wether hook is in progress, used to prevent infinte loops
  42. *
  43. * @var bool
  44. */
  45. var $in_progress = FALSE;
  46. /**
  47. * Constructor
  48. *
  49. */
  50. function __construct()
  51. {
  52. $this->_initialize();
  53. log_message('debug', "Hooks Class Initialized");
  54. }
  55. // --------------------------------------------------------------------
  56. /**
  57. * Initialize the Hooks Preferences
  58. *
  59. * @access private
  60. * @return void
  61. */
  62. function _initialize()
  63. {
  64. $CFG =& load_class('Config', 'core');
  65. // If hooks are not enabled in the config file
  66. // there is nothing else to do
  67. if ($CFG->item('enable_hooks') == FALSE)
  68. {
  69. return;
  70. }
  71. // Grab the "hooks" definition file.
  72. // If there are no hooks, we're done.
  73. if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/hooks.php'))
  74. {
  75. include(APPPATH.'config/'.ENVIRONMENT.'/hooks.php');
  76. }
  77. elseif (is_file(APPPATH.'config/hooks.php'))
  78. {
  79. include(APPPATH.'config/hooks.php');
  80. }
  81. if ( ! isset($hook) OR ! is_array($hook))
  82. {
  83. return;
  84. }
  85. $this->hooks =& $hook;
  86. $this->enabled = TRUE;
  87. }
  88. // --------------------------------------------------------------------
  89. /**
  90. * Call Hook
  91. *
  92. * Calls a particular hook
  93. *
  94. * @access private
  95. * @param string the hook name
  96. * @return mixed
  97. */
  98. function _call_hook($which = '')
  99. {
  100. if ( ! $this->enabled OR ! isset($this->hooks[$which]))
  101. {
  102. return FALSE;
  103. }
  104. if (isset($this->hooks[$which][0]) AND is_array($this->hooks[$which][0]))
  105. {
  106. foreach ($this->hooks[$which] as $val)
  107. {
  108. $this->_run_hook($val);
  109. }
  110. }
  111. else
  112. {
  113. $this->_run_hook($this->hooks[$which]);
  114. }
  115. return TRUE;
  116. }
  117. // --------------------------------------------------------------------
  118. /**
  119. * Run Hook
  120. *
  121. * Runs a particular hook
  122. *
  123. * @access private
  124. * @param array the hook details
  125. * @return bool
  126. */
  127. function _run_hook($data)
  128. {
  129. if ( ! is_array($data))
  130. {
  131. return FALSE;
  132. }
  133. // -----------------------------------
  134. // Safety - Prevents run-away loops
  135. // -----------------------------------
  136. // If the script being called happens to have the same
  137. // hook call within it a loop can happen
  138. if ($this->in_progress == TRUE)
  139. {
  140. return;
  141. }
  142. // -----------------------------------
  143. // Set file path
  144. // -----------------------------------
  145. if ( ! isset($data['filepath']) OR ! isset($data['filename']))
  146. {
  147. return FALSE;
  148. }
  149. $filepath = APPPATH.$data['filepath'].'/'.$data['filename'];
  150. if ( ! file_exists($filepath))
  151. {
  152. return FALSE;
  153. }
  154. // -----------------------------------
  155. // Set class/function name
  156. // -----------------------------------
  157. $class = FALSE;
  158. $function = FALSE;
  159. $params = '';
  160. if (isset($data['class']) AND $data['class'] != '')
  161. {
  162. $class = $data['class'];
  163. }
  164. if (isset($data['function']))
  165. {
  166. $function = $data['function'];
  167. }
  168. if (isset($data['params']))
  169. {
  170. $params = $data['params'];
  171. }
  172. if ($class === FALSE AND $function === FALSE)
  173. {
  174. return FALSE;
  175. }
  176. // -----------------------------------
  177. // Set the in_progress flag
  178. // -----------------------------------
  179. $this->in_progress = TRUE;
  180. // -----------------------------------
  181. // Call the requested class and/or function
  182. // -----------------------------------
  183. if ($class !== FALSE)
  184. {
  185. if ( ! class_exists($class))
  186. {
  187. require($filepath);
  188. }
  189. $HOOK = new $class;
  190. $HOOK->$function($params);
  191. }
  192. else
  193. {
  194. if ( ! function_exists($function))
  195. {
  196. require($filepath);
  197. }
  198. $function($params);
  199. }
  200. $this->in_progress = FALSE;
  201. return TRUE;
  202. }
  203. }
  204. // END CI_Hooks class
  205. /* End of file Hooks.php */
  206. /* Location: ./system/core/Hooks.php */
复制代码

可以看出codeigniter实现钩子机制的方式不够优雅,其实完全可以使用观察者模式来实现钩子机制,将挂载点当做监听的事件。

如何实现, codeigniter