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 相关文章推荐
使用网络地址转换实现多服务器负载均衡
Oct 09 PHP
php shell超强免杀、减少体积工具实现代码
Oct 16 PHP
php统计文章排行示例
Mar 04 PHP
typecho插件编写教程(五):核心代码
May 28 PHP
ThinkPHP2.x防范XSS跨站攻击的方法
Sep 25 PHP
WordPress开发中用于获取近期文章的PHP函数使用解析
Jan 05 PHP
CodeIgniter读写分离实现方法详解
Jan 20 PHP
浅谈PHP的排列组合(如输入a,b,c 输出他们的全部组合)
Mar 14 PHP
PHP框架laravel的.env文件配置教程
Jun 07 PHP
Laravel Intervention/image图片处理扩展包的安装、使用与可能遇到的坑详解
Nov 14 PHP
YII2.0框架行为(Behavior)深入详解
Jul 26 PHP
PHP延迟静态绑定使用方法实例解析
Sep 05 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
php Static关键字实用方法
2010/06/04 PHP
php笔记之常用文件操作
2010/10/12 PHP
关于php几种字符串连接的效率比较(详解)
2017/02/22 PHP
thinkphp5框架扩展redis类方法示例
2019/05/06 PHP
解决php用mysql方式连接数据库出现Deprecated报错问题
2019/12/25 PHP
ThinkPHP5.1+Ajax实现的无刷新分页功能示例
2020/02/10 PHP
js apply/call/caller/callee/bind使用方法与区别分析
2009/10/28 Javascript
基于JQuery框架的AJAX实例代码
2009/11/03 Javascript
jQuery 1.5 源码解读 面向中高阶JSER
2011/04/05 Javascript
node.js使用npm 安装插件时提示install Error: ENOENT报错的解决方法
2014/11/20 Javascript
浏览器中url存储的JavaScript实现
2015/07/07 Javascript
浅谈javascript原型链与继承
2015/07/13 Javascript
在windows上用nodejs搭建静态文件服务器的简单方法
2016/08/11 NodeJs
遍历json获得数据的几种方法小结
2017/01/21 Javascript
Angular.js实现多个checkbox只能选择一个的方法示例
2017/02/24 Javascript
微信小程序动态的加载数据实例代码
2017/04/14 Javascript
Vue键盘事件用法总结
2017/04/18 Javascript
WdatePicker.js时间日期插件的使用方法
2017/07/26 Javascript
深入理解vue.js中$watch的oldvalue与newValue
2017/08/07 Javascript
JS+canvas绘制的动态机械表动画效果
2017/09/12 Javascript
JS实现导出Excel的五种方法详解【附源码下载】
2018/03/15 Javascript
vue单页面实现当前页面刷新或跳转时提示保存
2018/11/02 Javascript
详解vue挂载到dom上会发生什么
2019/01/20 Javascript
微信小程序转发事件实现解析
2019/10/22 Javascript
[01:00:14]DOTA2官方TI8总决赛纪录片 真视界True Sight
2019/01/16 DOTA
python统计字符串中指定字符出现次数的方法
2015/04/04 Python
Windows系统下PhantomJS的安装和基本用法
2018/10/21 Python
Python面向对象程序设计之继承、多态原理与用法详解
2020/03/23 Python
解决Keras自带数据集与预训练model下载太慢问题
2020/06/12 Python
文员岗位职责
2013/11/09 职场文书
销售顾问岗位职责
2014/02/25 职场文书
银行行长竞聘演讲稿
2014/04/23 职场文书
2015年中学体育教师工作总结
2015/10/23 职场文书
如何使用CocosCreator对象池
2021/04/14 Javascript
死磕 java同步系列之synchronized解析
2021/06/28 Java/Android
MYSQL常用函数介绍
2022/05/05 MySQL