php中钩子(hook)的原理与简单应用demo示例


Posted in PHP onSeptember 03, 2019

本文实例讲述了php中钩子(hook)的原理与简单应用。分享给大家供大家参考,具体如下:

我们先来回顾下原本的开发流程;

产品汪搞出了一堆需求;

当用户注册成功后需要发送短信、发送邮件等等;

然后聪明机智勇敢的程序猿们就一扑而上;

把这些需求转换成代码扔在 用户注册成功 和 跳转到首页 之间;

没有什么能够阻挡;充满创造力的猿们;

<?php
class Test{
  public function index(){
    // 用户注册成功
      /*
       此处是一堆发送短信的代码
      */
      /*
       此处是一堆发送邮件的代码
      */
      /*
       此处是一堆其他功能的代码
      */
    // 前往网站首页
  }
}
$test=new Test();
$test->index();

如果每个功能都由不同的猿完成的话;

首先面临的就是代码会很杂乱;配合起来会比较麻烦;

那封装成函数吧;一方面会规范整洁写;另外方便重复调用;

没有什么能够阻挡;充满创造力的猿们;

<?php
class Test{
  public function index(){
    // 用户注册成功
    // 发送短信
    sendSms($phone);
    // 发送邮件
    sendSms($email);
    // 其他操作...
    // 前往网站首页
  }
}
/**
 * 发送短信通知
 * @param integer $phone 手机号
 */
function sendSMS($phone){
  // 此处是发送短信的代码
}
/**
 * 发送邮件通知
 * @param string $email 邮箱地址
 */
function sendEmail($email){
  // 此处是发送邮件的代码
}

这时候运营喵表示;

如果能在后台点点按钮就能设置是发邮件还是发短信;那想必是极好的;

没有什么能够阻挡;充满创造力的猿们;

<?php
class Test{
  public function index(){
    // 用户注册成功
    if ('如果设置了发送短信') {
      // 发送短信
      sendSms($phone);
    }
    if ('如果设置了发送邮件') {
      // 发送邮件
      sendSms($email);
    }
    // 其他操作...
    // 前往网站首页
  }
}
/**
 * 发送短信通知
 * @param integer $phone 手机号
 */
function sendSMS($phone){
  // 此处是发送短信的代码
}
/**
 * 发送邮件通知
 * @param string $email 邮箱地址
 */
function sendEmail($email){
  // 此处是发送邮件的代码
}

在一个封闭企业环境下这样搞是没有问题的;

然鹅;我们还有一位开放无私的猿领导要把程序开源出去造福其他猿类;

希望有更多的猿类来参与这个项目;共同开发功能;

如果大家都去改动这套程序;把自己的代码扔在 用户注册成功 和 跳转到首页 之间;

这显然是不靠谱的;想想都混乱的一塌糊涂;

那可不可以大家把自己写的代码放到某个目录下;

然后系统自动的根据配置项把这些代码加载到 用户注册成功 和 跳转到首页 之间呢?

好先定义如下目录

├─plugin // 插件目录
│  ├─plugin1 // 插件1
│  │  ├─config.php // 插件1的配置项
│  │  ├─index.php // 插件1的程序处理内容
│  ├─plugin2
│  │  ├─config.php
│  │  ├─index.php
│  ├─plugin3
│  │  ├─config.php
│  │  ├─index.php
│  ├─...
├─index.php // 业务逻辑

业务逻辑的代码:

<?php
class Test{
  public function index(){
    // 用户注册成功
    // 获取全部插件
    $pluginList=scandir('./plugin/');
    // 循环插件 // 排除. ..
    foreach ($pluginList as $k => $v) {
      if ($v=='.' || $v=='..') {
        unset($pluginList[$k]);
      }
    }
    echo "简易后台管理<hr>";
    // 插件管理
    foreach ($pluginList as $k => $v) {
      // 获取配置项
      $config=include './plugin/'.$v.'/config.php';
      $word=$config['status']==1 ? '点击关闭' : '点击开启';
      echo $config['title'].'<a href="./index.php?change='.$v.'" rel="external nofollow" >'.$word.'</a><br />';
    }
    echo '<hr>';
    // 输出插件内容
    foreach ($pluginList as $k => $v) {
      // 获取配置项
      $config=include './plugin/'.$v.'/config.php';
      if ($config['status']==1) {
        include './plugin/'.$v.'/index.php';
        // 运行插件
        Hook::run($v);
      }
    }
    // 前往网站首页
  }
}
// 插件类
class Hook{
  // 注册添加插件
  public static function add($name,$func){
    $GLOBALS['hookList'][$name][]=$func;
  }
  // 执行插件
  public static function run($name,$params=null){
    foreach ($GLOBALS['hookList'][$name] as $k => $v) {
      call_user_func($v,$params);
    }
  }
}
// 更改插件状态
if (isset($_GET['change'])) {
  // 获取到配置项
  $config=include './plugin/plugin'.substr($_GET['change'],-1).'/config.php';
  // 如果是开启 那就关闭 如果是关闭 则开启
  $config['status']=$config['status']==1 ? 0: 1;
  // 将更改后的配置项写入到文件中
  $str="<?php \\r\\n return ".var_export($config,true).';';
  file_put_contents('./plugin/'.$_GET['change'].'/config.php', $str);
  header('Location:./');
}
$test=new Test();
$test->index();

插件配置项代码:

<?php
 return array (
 'status' => 1, // 定义状态 1表示开启 0表示关闭
 'title' => '发送短信', // 插件的名称
);

插件的内容:

没错;这就是插件的思想;

当然这只是一个超级简单的示例;

完整的插件机制要包括插件的类型、数据库、审核等等;

如果使用过wordpress或者国内的discuz;

你就会发现一个好的程序并不仅仅是自身多么优秀;

而且重要的就是设计的扩展性有多好;能多方便的让大家去扩展它的功能;

想对插件深入研究的话;建议去阅读wordpress、discuz的源代码;

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
php中数据的批量导入(csv文件)
Oct 09 PHP
PHP编码转换
Nov 05 PHP
PHP实现的汉字拼音转换和公历农历转换类及使用示例
Jul 01 PHP
php获取用户浏览器版本的方法
Jan 03 PHP
php使用Cookie控制访问授权的方法
Jan 21 PHP
PHP访问Google Search API的方法
Mar 05 PHP
php微信高级接口群发 多客服
Jun 23 PHP
php json中文编码为null的解决办法
Dec 14 PHP
使用php自动备份数据库表的实现方法
Jul 28 PHP
PHP大文件分割上传 PHP分片上传
Aug 28 PHP
基于php中echo用逗号和用点号的区别详解
Jan 23 PHP
JS操作XML中DTD介绍及使用方法分析
Jul 04 PHP
php根据地址获取百度地图经纬度的实例方法
Sep 03 #PHP
Laravel使用Queue队列的技巧汇总
Sep 02 #PHP
PHP单文件上传原理及上传函数的封装操作示例
Sep 02 #PHP
PHP实现单文件、多个单文件、多文件上传函数的封装示例
Sep 02 #PHP
PHP 文件上传限制问题
Sep 01 #PHP
laravel框架模板之公共模板、继承、包含实现方法分析
Aug 30 #PHP
php中的钩子理解及应用实例分析
Aug 30 #PHP
You might like
如何取得中文字符串中出现次数最多的子串
2013/08/08 PHP
Yii框架连表查询操作示例
2019/09/06 PHP
tp5.0框架隐藏index.php入口文件及模块和控制器的方法分析
2020/02/11 PHP
js调试工具 Javascript Debug Toolkit 2.0.0版本发布
2008/12/02 Javascript
Node.js实战 建立简单的Web服务器
2012/03/08 Javascript
js split 的用法和定义 js split分割字符串成数组的实例代码
2012/05/13 Javascript
javascript游戏开发之《三国志曹操传》零部件开发(一)让静态人物动起来
2013/01/23 Javascript
js异常捕获方法介绍
2013/04/10 Javascript
jquery获取元素值的方法(常见的表单元素)
2013/11/15 Javascript
nodejs 提示‘xxx’ 不是内部或外部命令解决方法
2014/11/20 NodeJs
JavaScript File API文件上传预览
2016/02/02 Javascript
jQuery中数据缓存$.data的用法及源码完全解析
2016/04/29 Javascript
全面解析JavaScript中apply和call以及bind(推荐)
2016/06/15 Javascript
基于Bootstrap的Metronic框架实现页面链接收藏夹功能
2016/08/29 Javascript
bootstrap折叠调用collapse()后data-parent不生效的快速解决办法
2017/02/23 Javascript
React学习之JSX与react事件实例分析
2020/01/06 Javascript
详解vue3.0 diff算法的使用(超详细)
2020/07/01 Javascript
JavaScript代码模拟鼠标自动点击事件示例
2020/08/07 Javascript
[46:58]完美世界DOTA2联赛PWL S3 Forest vs LBZS 第一场 12.17
2020/12/19 DOTA
Python os模块学习笔记
2015/06/21 Python
Python Flask前后端Ajax交互的方法示例
2018/07/31 Python
keras 多gpu并行运行案例
2020/06/10 Python
Python爬虫之爬取淘女郎照片示例详解
2020/07/28 Python
html5 Canvas画图教程(5)—canvas里画曲线之arc方法
2013/01/09 HTML / CSS
HTML5图片预览实例分享
2014/06/04 HTML / CSS
金宝贝童装官网:Gymboree
2016/08/31 全球购物
澳大利亚领先的运动鞋商店:Hype DC
2018/03/31 全球购物
东南亚排名第一的服务市场:kaodim
2019/03/28 全球购物
杭州联环马网络笔试题面试题
2013/08/04 面试题
资料员的岗位职责
2013/11/20 职场文书
大学生自我鉴定评语
2014/01/27 职场文书
2014党员四风对照检查材料思想汇报
2014/09/17 职场文书
休学证明范本
2015/06/19 职场文书
校园开放日新闻稿
2015/07/17 职场文书
2015年公司国庆放假通知
2015/07/30 职场文书
Android studio 简单计算器的编写
2022/05/20 Java/Android