作为程序员,设计出优雅而完美的系统,永远是让我们非常兴奋的事情。高手不在于你会多少语言,而在于你有多高的思想。
 
  在设计中,怎么体现自身价值,那就是要比别人多想几步。
 
  讲钩子程序,起源是对用户提交的参数校验(永远不要相信用户),一开始为了赶工期,按照比较传统的方式,每个接口里重复性的对参数进行过滤。后面随着业务的发展(功能迭代),系统的维护成本越来越高,遂想一个更高级的方式进行处理。借鉴同事之前的代码,使用钩子方式进行重构。
 
  之前写过javascript 钩子机制, 偏后钩,可以互相借鉴下。
 
脉路
  
 
 
 
概念
  
  把一段程序块(执行体)通过某种方式挂入系统中,从而获得对系统的控制权。
 
       注意下图挂钩位置:
 

 
 
应用
  
  小的方面: 进行基础的入参校验或消息过滤。
  大的方面:组件化,可在系统中进行插拔管理。
  
  优点:
    1、降低系统的耦合度;
    2、降低开发、测试人力成本,用少量的代码实现高可用功能;
    3、提高模块间的可用性;
    4、通过配置(配置文件or数据库)的方式升级接口。
  缺点:
    学习成本过高;
    系统复杂度提升;
 
 
实现思想
  
 

     配置文件的方式进行钩子定义、钩子链管理(使用“组”的概念)、挂钩。
 
  

    钩子:程序执行体;
      钩子组: 钩子链的分类定义;
           挂钩: 入口(MVC中action或者controller)与钩子组进行绑定。
 
 
 
实现方式
  
   
 
  
       挂钩器(继承类):
  1. <?php
  2. /**
  3. * @name Service_Page_Test
  4. * @desc page层对接第三方抽象类
  5. * @author
  6. */
  7. abstract class Service_Page_Test
  8. {
  9. public $hookGroupPrev = null; // 前钩子组
  10. public $hookGroupAfter = null; // 后钩子组
  11. public $hookReturn = array(); //钩子返回值
  12. public $reqData = null; // page模块分析的数据
  13.  
  14. /**
  15. * 获取需要验证的参数配置
  16. * @return array
  17. */
  18. public function _getCheckParams()
  19. {
  20. return array();
  21. }
  22.  
  23. /**
  24. * 入口方法
  25. * @param array $arrInput
  26. * @return array
  27. */
  28. public function execute($arrInput)
  29. {
  30. $res = array(
  31. 'errno' => Test_Errno::ERRNO_SUCCESS,
  32. 'errmsg' => Test_Errno::$ERRMSG[Test_Errno::ERRNO_SUCCESS],
  33. );
  34. try {
  35. $this->_init($arrInput);
  36. $this->_beforeExecute();
  37. $res = $this->doExecute($arrInput);
  38. $this->_afterExecute();
  39. } catch (Test_Exception $e) {
  40. $res = array(
  41. 'errno' => $e->getCode(),
  42. 'errmsg' => $e->getMessage(),
  43. );
  44. } catch (Exception $e) {
  45. $res = array(
  46. 'errno' => $e->getCode(),
  47. 'errmsg' => $e->getMessage(),
  48. );
  49.  
  50. }
  51. return $res;
  52. }
  53.  
  54. /**
  55. * auto exec
  56. * @param array $arrInput
  57. * @throws Exception
  58. * @return array
  59. */
  60. protected function doExecute($arrInput){
  61. }
  62.  
  63. /**
  64. * 获取权限信息
  65. * @param array $arrInput
  66. * @return array
  67. */
  68. public function _init($arrInput)
  69. {
  70. $pageModulesConf = Conf::getConf('page/' . get_class($this));
  71. $this->reqData = $arrInput;
  72. $this->hookGroupPrev[] = $pageModulesConf['hook_group']['prev'];
  73. $this->hookGroupAfter[] = $pageModulesConf['hook_group']['after'];
  74. }
  75.  
  76. /**
  77. * 执行filter
  78. * @param string
  79. */
  80. public function _beforeExecute()
  81. {
  82. if (!empty($this->hookGroupPrev) && is_array($this->hookGroupPrev)) {
  83. foreach ($this->hookGroupPrev as $hookGroups) {
  84. foreach ($hookGroups as $hookGroup) {
  85. $this->_executeHook($hookGroup, $this->reqData);
  86. }
  87. }
  88. }
  89. }
  90.  
  91. /**
  92. * @param array $arrInput
  93. * @return array
  94. */
  95. public function _afterExecute()
  96. {
  97. if (!empty($this->hookGroupAfter) && is_array($this->hookGroupAfter)) {
  98. foreach ($this->hookGroupAfter as $hookGroups) {
  99. foreach ($hookGroups as $hookGroup) {
  100. $this->_executeHook($hookGroup, $this->reqData);
  101. }
  102. }
  103. }
  104. }
  105.  
  106. /**
  107. * 执行filter
  108. * @param string
  109. */
  110. public function _executeHook($hookGroup, $reqData)
  111. {
  112.  
  113. $hookGroupConf = Conf::getConf('hook/group/' . $hookGroup);
  114. if(!empty($hookGroupConf)){
  115. foreach($hookGroupConf as $hook){
  116. $hookConf = Conf::getConf('hook/hook/' . $hook);
  117. $class = $hookConf['class'];
  118. $method = $hookConf['method'];
  119. $inputParams = isset($hookConf['getInputParams']) ? $this->{$hookConf['getInputParams']}() : null;
  120. if (class_exists($class)) {
  121. $obj = new $class();
  122. if (method_exists($obj, $method)) {
  123. $this->hookReturn[$hook][] = $obj->$method($inputParams, $reqData);
  124. }
  125. }
  126. }
  127. }
  128.  
  129. }
  130.  
  131. }

  

  hook.conf

  1. # 钩子组
    [group]
  2. [.check_req_customer]
  3. : checkReqCustomerBaseInfo
  4. [.after_demo]
  5. : afterDemo
  6.  
  7. # 钩子
  8. [hook]
  9. [.checkReqCustomerBaseInfo]
  10. class: Service_Page_Hook_Customer
  11. method: checkBaseInfo
  12. getInputParams: _getCheckParams
  13.  
  14. [.afterDemo]
  15. class: Service_Page_Hook_Customer
  16. method: afterDemo
  17. getInputParams: _getCheckParams
  page.conf
  1. [Service_Page_Input]
  2. #绑定钩子组
  3. [.hook_group]
  4. [..prev]
  5. 0 : check_req_customer
  6. [..after]
  7. 0 : after_demo

  

 
 

 

推荐
 
 
 
 
 
 
 

php钩子程序设计的更多相关文章

  1. c++程序设计之编程思想

    代码块愈小,代码的功能就愈容易管理,代码的处理和移动就愈轻松. 任何一个傻瓜都能写出计算机可以理解的代码,唯有写出人类容易理解的代码,才是优秀的程序员. 绝大多数情况下,函数应该放在它所使用的数据的所 ...

  2. Java动态程序设计:反射介绍

    使用运行的类的信息使你的程序设计更加灵活 反射授予了你的代码访问装载进JVM内的Java类的内部信息的权限,并且允许你编写在程序执行期间与所选择的类的一同工作的代码,而不是在源代码中.这种机制使得反射 ...

  3. 使用PreTranslateMessage替代钩子函数处理键盘消息

    2002年左右,我所在公司在开发基于H.323的VoIP电话系统(用了以色列一家公司的库,具体名字忘记了). 去电信科技研究院测试系统,同事发现处理键盘消息总有一些莫名其妙的问题,比如延迟或异常. 我 ...

  4. Windows环境下32位汇编语言程序设计(典藏版)

    Windows环境下32位汇编语言程序设计(典藏版)(含CD光盘1张)(年,经典再现!) 罗云彬 著 ISBN 978-7-121-20759-4 2013年7月出版 定价:99.00元 756页 1 ...

  5. 利用钩子函数来捕捉键盘响应的windows应用程序

    一:引言: 你也许一直对金山词霸的屏幕抓词的实现原理感到困惑,你也许希望将你的键盘,鼠标的活动适时的记录下来,甚至你想知道木马在windows操作系统是怎样进行木马dll的加载的…..其实这些都是用到 ...

  6. 《windows核心编程系列》十八谈谈windows钩子

    windows应用程序是基于消息驱动的.各种应用程序对各种消息作出响应从而实现各种功能. windows钩子是windows消息处理机制的一个监视点,通过安装钩子能够达到监视指定窗体某种类型的消息的功 ...

  7. 【windows核心编程】系统消息与自定义钩子(Hook)使用

    一.HOOk Hook是程序设计中最为灵活多变的技巧之一,在windows下,Hook有两种含义: 1.系统提供的消息Hook机制 2.自定义的Hook编程技巧 其中,由系统提供的消息钩子机制是由一系 ...

  8. VC++开发Windows系统全局钩子

    本文的大部分内容属于对一篇网文的实践与练习,同时参考的还有一本书,在此向网文与书的作者表示敬意. 这个程序是一个windows系统键盘监控程序,随着开机自动启动,可以监控系统中各用户的键盘,并将按键记 ...

  9. Windows环境下32位汇编语言程序设计(典藏版)

    <Windows环境下32位汇编语言程序设计(典藏版) > 基本信息 作者: 罗云彬 出版社:电子工业出版社 ISBN:9787121207594 上架时间:2013-7-8 出版日期:2 ...

随机推荐

  1. NHibernate中使用memcache二级缓存

    在NHibernate中使用memcache二级缓存 一.Windows下安装Memcache  1. 下载   http://jehiah.cz/projects/memcached-win32/  ...

  2. Grunt使用入门

    Grunt使用入门 (by vczero) 一.前言 项目中一直在使用Grunt,只是对Grunt的基本使用,却未系统的总结过.为什么要构建工具?一句话:自动化.对于需要反复重复的任务,例如压缩(mi ...

  3. .NET MVC4 实训记录之二(扩展WebSecurity模型下的UserProfile表)

    使用VS2013创建MVC4项目后,自动生成的代码中默认使用WebSecurity模型创建用户管理,生成以下数据库:

  4. AngularJS Change Path Without Reloading

    To change path URL with AngularJS, $location.path() is passed the new URL as a parameter, and the pa ...

  5. Python语言在企业级应用上的十大谬误

    英文原文:https://www.paypal-engineering.com/2014/12/10/10-myths-of-enterprise-python/ 翻译原文:http://www.os ...

  6. Shards

    跟我一起云计算(5)——Shards   什么是sharding Sharding的基本思想就要把一个数据库切分成多个部分放到不同的数据库 (server)上,从而缓解单一数据库的性能问题.不太严格的 ...

  7. 使用Entity Framework 4进行代码优先开发

    [原文地址]Code-First Development with Entity Framework 4   .NET 4随带发布了一个改进版的Entity Framework(EF)- 一个位于Sy ...

  8. jquery实现城市选择器效果(二级联动)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. ios开发实践之UIDatePicker(已对之前无法解决的问题做了解答)

    需求:要做一个生日选择的控件,但除了选择之外还需要自定义几个控件,跟生日选择控件组合一起. 做法:自定义了一个UIImageView,并且作为背景.在这个背景view上再添加其他button和时间选择 ...

  10. node.js系列笔记之fs模块《二》

    一:感触 最近工作比较忙,感觉也比较多,因为工作上的不顺利,再加上加班比较多,所以最近心情不是很好,再加上英语能力差到不行,所以最近半个月学习进度也比较慢, 但还是告诉自己每天都坚持学一点,即使今天心 ...