当前位置:首页 > CMS教程 > Thinkphp > 列表

thinkphp(php)插件钩子(hooks)分析的简单实现机制

发布:smiling 来源: PHP粉丝网  添加日期:2023-07-02 09:28:07 浏览: 评论:0 

现在主流的cms或者blog等系统中,都内置的有插件系统,但是层层深入、剖析实现的方式,其实都是最简单的钩子的复杂化的实现。

钩子是插件执行的触发器;插件就像挂在钩子上的东西;插件只有实现相应钩子方法,并安装启用成功后才能执行。

开发者也可以用hook('test')方法在控制器只加入钩子,让你的应用具有更好的扩展性;同时也可以模板里加入钩子{:hook('footer')};钩子也支持传入参数hook('footer',array('test'=>1));

向系统暴露你的钩子,就是把你的钩子在相应的文件里列出来,系统会来检测。

{:hooks('documentDetailAfter')}

这个的意思就是:相当于在这边 打一个点 ,我们可以将插件挂载到那

官方的说法是:文档末尾显示显示的 钩子

意思就是说,在文档末尾的时候,会自动调用挂载在那个 钩子 上的插件

举例说明

php中所谓的钩子,其实就是一种事件驱动,主要分为‘注册事件’、‘触发事件’两步。所谓‘注册事件’,即目的是给未来可能发生的'事情'起一个名字,名字,可以用单例模式或者注册 为一个全局的变量,用的时候直接在对应的方法或者类再或者函数中插入这个变量即可;‘触发事件’,本质上就是在事件的全局变量中查询要触发的时间名称,然后找到注册号的类与方法,实例化运行。

举个例子来说明一下。

项目经理给我们了如下的需求:

第一天:开发注册的功能。

程序员巴拉巴拉,三下五除二就完成了。

第二天:在注册前添加发送短信验证码的功能。

程序员巴拉巴拉,三峡五除二就又完成了。

第三天:注册完成之后,给用户添加相应的积分。

程序员又开始巴拉巴拉ing……

  1. class Register{ 
  2.     public function index(){ 
  3.         /** 
  4.          * 第二天发送短信功能 
  5.          */ 
  6.           
  7.         /** 
  8.          * 第一天注册代码 
  9.          */ 
  10.           
  11.         /** 
  12.          * 第三天增加积分功能  
  13.          */ 
  14.     } 

这样一个人开发还好,多个人开发,势必会造成配合麻烦的问题,同时代码也会变得混乱。

作为优秀程序员的我们,当然不容许我们程序中代码冗余、混乱的出现,于是我们把方法写成函数独立出来,方便调用与代码简介。于是形成如下代码:

  1. class Register{ 
  2.     public function index(){ 
  3.         /** 
  4.          * 第二天发送短信功能 
  5.          */ 
  6.          sendMsg($data); 
  7.         /** 
  8.          * 第一天注册代码 
  9.          */ 
  10.           
  11.         /** 
  12.          * 第三天增加积分功能  
  13.          */ 
  14.         sendIntegral($data); 
  15.     } 
  16. /** 
  17.  * 发送短信 
  18.  * @param  {[type]} $data [description] 
  19.  * @return {[type]}       [description] 
  20.  */ 
  21. function sendMsg($data){ 
  22.     /* 
  23.             balabala 
  24.      */ 
  25. /** 
  26.  * 赠送积分 
  27.  * @param  {[type]} $data [description] 
  28.  * @return {[type]}       [description] 
  29.  */ 
  30. function sendIntegral($data){ 
  31.     /* 
  32.             balabala 
  33.      */ 

但是我们想要把程序开元出去让更多的人参与,这种直接修改源码码的方式始终不是太好,这个时候,我们就可以使用钩子的方式,在注册成功前后注册两个钩子,我们只需要把钩子告诉开发人员就行了,这样他们不用改变源码码就可以轻易的进行拓展。

  1. class Register{ 
  2.     public function index(){ 
  3.           
  4.         //注册前钩子 
  5.         Hook::run('registerBefore'); 
  6.         /** 
  7.          * 注册代码 
  8.          */ 
  9.           
  10.         //注册后钩子 
  11.         Hook::run('registerAfter'); 
  12.     } 

钩子的简单实现代码

目录结构:../hook/Hook.php

钩子核心类Hook.php:

  1. <?php 
  2.  
  3. namespace hook; 
  4. class Hook{ 
  5.       
  6.     static protected $hook = []; 
  7.       
  8.     /** 
  9.      * 插件注册 
  10.      * @param [type] $name   [description] 
  11.      * @param [type] $addons [description] 
  12.      */ 
  13.     static public function add($name,$addons){ 
  14.         self::$hook[$name] = $addons
  15.     } 
  16.     /** 
  17.      * 插件执行 
  18.      * @param  [type] $name [description] 
  19.      * @return [type]       [description] 
  20.      */ 
  21.     static public function run($name){ 
  22.         if(isset(self::$hook[$name])){ 
  23.             $method = (new self::$hook[$name]()); 
  24.                call_user_func([$method,$name]); 
  25.         } 
  26.           
  27.     } 

简单的插件demo:

  1. <?php 
  2. namespace addons\demo; 
  3. class Demo{ 
  4.     public function registerBefore(){ 
  5.         echo 'registerBefore'.'</br>'
  6.     } 
  7.     public function registerAfter(){ 
  8.         echo 'registerAfter'.'</br>'
  9.     }     

插件实现的地方,即上文的注册的文件:

  1. <?php 
  2. namespace index\controller; 
  3. use hook\Hook; 
  4. class Index{ 
  5.     public function index(){ 
  6.         Hook::run('registerBefore'); 
  7.         echo '注册完成'.'</br>'
  8.         Hook::run('registerAfter'); 
  9.           
  10.     } 

入口文件index.php

  1. <?php 
  2. use index\controller\Index; 
  3. spl_autoload_register('autoload'); 
  4. function autoload($name){ 
  5.     require_once('/'.str_replace('\\','/',$name).'.php'); 
  6. //插件注册 
  7. hook\Hook::add('registerBefore','\\addons\\demo\\Demo'); 
  8. hook\Hook::add('registerAfter','\\addons\\demo\\Demo'); 
  9. //调用 
  10. $index = new Index(); 
  11. $index->index(); 

运行接口如下:

registerBefore

注册完成

registerAfter

如果要添加新的功能,程序员只要修改demo的插件就可,如果要拓展新的功能,只需要拓展registerBefore和registerAfter即可。

总结:

可以说,钩子就是挂载点。

挂载点:在系统中提供给你一个挂载点,我们可以进行插件开发,开发完成后,我们将其挂载到 挂载点上,会自动调用执行。

Tags: thinkphp插件钩子 hooks

分享到: