网络编程
位置:首页>> 网络编程>> php编程>> thinkphp(php)插件钩子(hooks)分析的简单实现机制

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

  发布时间:2023-05-25 09:27:58 

标签:php,插件,钩子,hooks

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

前言

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

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

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

{:hooks('documentDetailAfter')}

这个的意思就是:相当于在这边 打一个点 ,我们可以将插件挂载到那
官方的说法是:文档末尾显示显示的 钩子
意思就是说,在文档末尾的时候,会自动调用挂载在那个 钩子 上的插件

举例说明

php中所谓的钩子,其实就是一种事件驱动,主要分为‘注册事件’、‘触发事件’两步。所谓‘注册事件’,即目的是给未来可能发生的'事情'起一个名字,名字,可以用单例模式或者注册 为一个全局的变量,用的时候直接在对应的方法或者类再或者函数中插入这个变量即可;‘触发事件’,本质上就是在事件的全局变量中查询要触发的时间名称,然后找到注册号的类与方法,实例化运行。
举个例子来说明一下。
项目经理给我们了如下的需求:
第一天:开发注册的功能。
程序员巴拉巴拉,三下五除二就完成了。
第二天:在注册前添加发送短信验证码的功能。
程序员巴拉巴拉,三峡五除二就又完成了。
第三天:注册完成之后,给用户添加相应的积分。
程序员又开始巴拉巴拉ing……

class Register{
       public function index(){
           /**
            * 第二天发送短信功能
            */
           
           /**
            * 第一天注册代码
            */
           
           /**
            * 第三天增加积分功能
            */
       }
   }

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

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

class Register{
       public function index(){
           /**
            * 第二天发送短信功能
            */
            sendMsg($data);
           /**
            * 第一天注册代码
            */
           
           /**
            * 第三天增加积分功能
            */
           sendIntegral($data);
       }
   }
   /**
    * 发送短信
    * @param  {[type]} $data [description]
    * @return {[type]}       [description]
    */
   function sendMsg($data){
       /*
               balabala
        */
   }
   /**
    * 赠送积分
    * @param  {[type]} $data [description]
    * @return {[type]}       [description]
    */
   function sendIntegral($data){
       /*
               balabala
        */
   }

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

class Register{
       public function index(){
           
           //注册前钩子
           Hook::run('registerBefore');
           /**
            * 注册代码
            */
           
           //注册后钩子
           Hook::run('registerAfter');
       }
   }

钩子的简单实现代码

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

钩子核心类Hook.php:

<?php
   
   namespace hook;
   class Hook{
       
       static protected $hook = [];
       
       /**
        * 插件注册
        * @param [type] $name   [description]
        * @param [type] $addons [description]
        */
       static public function add($name,$addons){
           self::$hook[$name] = $addons;
       }
       /**
        * 插件执行
        * @param  [type] $name [description]
        * @return [type]       [description]
        */
       static public function run($name){
           if(isset(self::$hook[$name])){
               $method = (new self::$hook[$name]());
                  call_user_func([$method,$name]);
           }
           
       }
   }

简单的插件demo:

<?php
   namespace addons\demo;
   class Demo{
       public function registerBefore(){
           echo 'registerBefore'.'</br>';
       }
       public function registerAfter(){
           echo 'registerAfter'.'</br>';
       }    
   }

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

<?php
   namespace index\controller;
   use hook\Hook;
   class Index{
       public function index(){
           Hook::run('registerBefore');
           echo '注册完成'.'</br>';
           Hook::run('registerAfter');
           
       }
   }

入口文件index.php

<?php
   use index\controller\Index;
   spl_autoload_register('autoload');
   function autoload($name){
       require_once('/'.str_replace('\\','/',$name).'.php');
   }
   //插件注册
   hook\Hook::add('registerBefore','\\addons\\demo\\Demo');
   hook\Hook::add('registerAfter','\\addons\\demo\\Demo');
   //调用
   $index = new Index();
   $index->index();

运行接口如下:

  •     registerBefore

  •     注册完成

  •     registerAfter

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

总结

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

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

0
投稿

猜你喜欢

  • 摘要: 本文由简到繁地介绍了以jQuery作为蓝本的js框架开发步聚, 希望借助本文大家对jQuery这样的框架内部有一个大致的认识。推荐:
  • 原来图片自适应宽度一般都是通过Javascript来解决的,但是多少还是比较麻烦。还有一种通过设置外层容器overflow:hidden属性
  • 在项目开发中,经常出现这样的需求。在新增或修改一个主表数据时,对应的从表也要进行同步,此时我们是怎么操作的了?典型的方法就是对于主表的各数据
  • 这篇文章所说的视觉元素是指:在一个网站中除去内容(文本、图片、视频、音频等)之外的一些元素。比如图标,背景色,以及背景图案。视觉元素的设计是
  • 最近和一程序员合作项目。弄的我头都大了~埋怨我的CSS命名看不懂~得按照他的来。结果我打开他的页面,看了看,从头第一个开始就是content
  • 这个问题我在给新云CMS升级时遇到了,按照升级步骤做完,后台登录时,出现“HTTP 错误 500.100 - 内部服务器错误 - ASP 错
  • 方法1:/** 功能:数据备份/恢复文件简易方法* 以日期为单位,一天一个备份文件,以当天最后备份为准* 用提交表单的形式进行操作,* 其中
  • 如果遇到与文件许可有关的问题,可能数启动mysqld时UMASK环境变量设置得不正确。例如,当你创建表时,MySQL可能会发出下述错误消息:
  • 由于XML本身的诸多优点,XML技术已被广泛的使用,目前的好多软件技术同XML紧密相关,比如微软的.net 平台对xml提供了强大的支持,提
  • ASP给图片加水印是需要组件的...常用的有aspjpeg软件和中国人自己开发的wsImage软件,可以上网搜索下载这两个软件,推荐使用咱们
  • MySQL内部复制功能是建立在两个或两个以上服务器之间,通过设定它们之间的主-从关系来实现的。其中一个作为主服务器,其它的作为从服务器。本节
  • 内容摘要:    模拟网页下拉菜单中有几个比较关键的CSS属性:position、left、top、
  • 三天前,你说下面的图是 PS 的,我信。而今天,这的的确确是张截图 -- 是的,这已经 不是梦想,是现实 -- 但实现梦想的不是微软,是 G
  • 现在越来越多的浏览器有拦截弹出窗口的功能。广告弹出来给拦掉了就无所谓,要是客户在付款时给拦掉了可就不能乱算了。Gmail的“哎呀”算是经典,
  •   很早以前就说过,IE8的标准模式已经不再支持滤镜了,不过IE仍然留了一条后路,你可以在CSS中这样写滤镜:-ms-filter
  • 讲这个方法之前,我们应该先了解下插入节点时浏览器会做什么。在浏览器中,我们一旦把节点添加到document.body(或者其他节点)中,页面
  • 研究了几天Adodb.stream和XMLHTTP的应用,找了不少很有趣的教程,下面的代码是将一个远程的页面,图片地址保存到本地的实例。将代
  • SQL Server 2000 清理日志精品教程SQL Server 2000 数据库日志太大!如何清理SQL Server 2000的日志
  • folder.htm<html><head><title>闪亮日子之在线创建文件夹</title&
  • 如果原来没有使用过正则表达式,那么可能对这个术语和概念会不太熟悉。不过,它们并不是您想象的那么新奇。请回想一下在硬盘上是如何查找文件的。您肯
手机版 网络编程 asp之家 www.aspxhome.com