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 相关文章推荐
oracle资料库函式库
Oct 09 PHP
NOD32 v2.70.32 简体中文封装版 提供下载了
Feb 27 PHP
php+mysql写的简单留言本实例代码
Jul 25 PHP
兼容firefox,chrome的网页灰度效果
Aug 08 PHP
ajax完美实现两个网页 分页功能的实例代码
Apr 16 PHP
php中使用getimagesize获取图片、flash等文件的尺寸信息实例
Apr 29 PHP
PHP从FLV文件获取视频预览图的方法
Mar 12 PHP
基于CakePHP实现的简单博客系统实例
Jun 28 PHP
详解WordPress中过滤链接与过滤SQL语句的方法
Dec 18 PHP
Thinkphp5.0 框架的请求方式与响应方式分析
Oct 14 PHP
Yii框架组件的事件机制原理与用法分析
Apr 07 PHP
Yii 实现数据加密和解密
Mar 09 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
自己做矿石收音机
2021/03/02 无线电
求PHP数组最大值,最小值的代码
2011/10/31 PHP
PHP实现根据浏览器跳转不同语言页面代码
2013/08/02 PHP
php+mysqli数据库连接的两种方式
2015/01/28 PHP
PHP信号处理机制的操作代码讲解
2019/04/19 PHP
Javascript Cookie读写删除操作的函数
2010/03/02 Javascript
分享一道笔试题[有n个直线最多可以把一个平面分成多少个部分]
2012/10/12 Javascript
jquery移动listbox的值原理及代码
2013/05/03 Javascript
如何在JavaScript中实现私有属性的写类方式(二)
2013/12/04 Javascript
jQuery 2.0.3 源码分析之core(一)整体架构
2014/05/27 Javascript
Javascript MVC框架Backbone.js详解
2014/09/18 Javascript
JavaScript学习笔记之JS对象
2015/01/22 Javascript
JS实现的另类手风琴效果网页内容切换代码
2015/09/08 Javascript
基于JavaScript实现高德地图和百度地图提取行政区边界经纬度坐标
2016/01/22 Javascript
Javascript复制实例详解
2016/01/28 Javascript
基于Bootstrap使用jQuery实现简单可编辑表格
2016/05/04 Javascript
功能强大的Bootstrap组件(结合js)
2016/08/03 Javascript
利用node.js本地搭建HTTP服务器
2017/04/19 Javascript
JavaScript基于replace+正则实现ES6的字符串模版功能
2017/04/25 Javascript
template.js前端模板引擎使用详解
2017/10/10 Javascript
vue中使用vue-router切换页面时滚动条自动滚动到顶部的方法
2017/11/28 Javascript
AngularJS监听ng-repeat渲染完成的方法
2018/03/20 Javascript
如何使node也支持从url加载一个module详解
2018/06/05 Javascript
[04:29]2014DOTA2国际邀请赛 主赛事第三日TOPPLAY
2014/07/21 DOTA
详解Python安装tesserocr遇到的各种问题及解决办法
2019/03/07 Python
django框架model orM使用字典作为参数,保存数据的方法分析
2019/06/24 Python
TensorFlow的环境配置与安装教程详解(win10+GeForce GTX1060+CUDA 9.0+cuDNN7.3+tensorflow-gpu 1.12.0+python3.5.5)
2020/06/22 Python
大学生收银员求职信分享
2014/01/02 职场文书
优秀电子工程系毕业生求职信
2014/05/24 职场文书
教师党员岗位承诺书
2014/05/29 职场文书
室内趣味活动方案
2014/08/24 职场文书
国庆节标语大全
2014/10/08 职场文书
2014年客服工作总结与计划
2014/12/09 职场文书
接触艺术对孩子学习思维有益
2019/08/06 职场文书
PostGIS的安装与入门使用指南
2022/01/18 PostgreSQL
使用python创建股票的时间序列可视化分析
2022/03/03 Python