PHP中的插件机制原理和实例


Posted in PHP onJuly 08, 2014

PHP项目中很多用到插件的地方,更尤其是基础程序写成之后很多功能由第三方完善开发的时候,更能用到插件机制,现在说一下插件的实现。特点是无论你是否激活,都不影响主程序的运行,即使是删除也不会影响。

从一个插件安装到运行过程的角度来说,主要是三个步骤:

1.插件安装(把插件信息收集进行采集和记忆的过程,比如放到数据库中或者XML中)

2.插件激活(打开插件,让监听插件的地方开始进行调用)

3.插件运行(插件功能的实现)

从一个插件的运行上来说主要以下几点:

1.插件的动态监听和加载(插件的信息获取)

2.插件的动态触发(插件的运行)

一个完善的插件系统主要包括以下:

1.插件安装及卸载

2.插件打开与关闭

3.插件信息获取

4.插件调度(插件经理)

5.插件主体

在程序的编写上主要实现以下:

1.插件的注册和初始化

2.判断激活条件

3.钩子激活

4.运行插件

实例代码:

<?php
/** 
* PluginManager Class 
* 
* 插件机制的实现核心类 
* 
* @link https://3water.com/ 
*/ 
class PluginManager 
{ 
  /** 
   * 监听已注册的插件 
   * 
   * @access private 
   * @var array 
   */ 
  private $_listeners = array(); 
   /** 
   * 构造函数 
   * 
   * @access public 
   * @return void 
   */ 
  public function __construct() 
  { 
    #这里$plugin数组包含我们获取已经由用户激活的插件信息 
   #为演示方便,我们假定$plugin中至少包含 
   #$plugin = array( 
    #  'name' => '插件名称', 
    #  'directory'=>'插件安装目录' 
    #); 
   
 
   // $plugins = get_active_plugins();#这个函数请自行实现 
 
    //函数实现后的最终数据结构效果如下
    $plugins=array(array("directory"=>"demo",
    "name"=>"DEMO"));
 
 
    if($plugins) 
    { 
      foreach($plugins as $plugin) 
 
      {//假定每个插件文件夹中包含一个actions.php文件,它是插件的具体实现 
        if (@file_exists(STPATH .'plugins/'.$plugin['directory'].'/actions.php')) 
        { 
          include_once(STPATH .'plugins/'.$plugin['directory'].'/actions.php'); 
          $class = $plugin['name'].'_actions'; 
          if (class_exists($class)) 
          { 
            //初始化所有插件 
            //$this 是本类的引用
            new $class($this); 
          } 
        } 
      } 
    } 
    #此处做些日志记录方面的东西 
  } 
 
  /** 
   * 注册需要监听的插件方法(钩子) 
   * 
   * @param string $hook 
   * @param object $reference 
   * @param string $method 
   */ 
  function register($hook, &$reference, $method) 
  { 
    //获取插件要实现的方法 
    $key = get_class($reference).'->'.$method; 
    //将插件的引用连同方法push进监听数组中 
    $this->_listeners[$hook][$key] = array(&$reference, $method); 
    #此处做些日志记录方面的东西 
  } 
  /** 
   * 触发一个钩子 
   * 
   * @param string $hook 钩子的名称 
   * @param mixed $data 钩子的入参 
   *  @return mixed 
   */ 
  function trigger($hook, $data='') 
  { 
    $result = ''; 
    //查看要实现的钩子,是否在监听数组之中 
    if (isset($this->_listeners[$hook]) && is_array($this->_listeners[$hook]) && count($this->_listeners[$hook]) > 0) 
    { 
      // 循环调用开始 
      foreach ($this->_listeners[$hook] as $listener) 
      { 
        // 取出插件对象的引用和方法 
        $class =& $listener[0]; 
        $method = $listener[1]; 
        if(method_exists($class,$method)) 
        { 
          // 动态调用插件的方法 
          $result .= $class->$method($data); 
        } 
      } 
    } 
    #此处做些日志记录方面的东西 
    return $result; 
  } 
} 
 
define(STPATH, "./");
 
$pluginManager=new PluginManager();
 
$pluginManager->trigger("demo");

demo插件文件:

<?php
/**
 * 这是一个Hello World简单插件的实现
 *
 * @link    https://3water.com/
 */
/**
 *需要注意的几个默认规则:
 *  1. 本插件类的文件名必须是action
 *  2. 插件类的名称必须是{插件名_actions}
 */
class DEMO_actions
{
  //解析函数的参数是pluginManager的引用
  function __construct(&$pluginManager)
  {
    //注册这个插件
    //第一个参数是钩子的名称
    //第二个参数是pluginManager的引用
    //第三个是插件所执行的方法
    $pluginManager->register('demo', $this, 'say_hello');
  }
 
  function say_hello()
  {
    echo 'Hello World';
  }
}
PHP 相关文章推荐
新手配置 PHP 调试环境(IIS+PHP+MYSQL)
Jan 10 PHP
PHP优于Node.js的五大理由分享
Sep 15 PHP
php多文件上传功能实现原理及代码
Apr 18 PHP
分享下PHP register_globals 值为on与off的理解
Sep 26 PHP
php GUID生成函数和类
Mar 10 PHP
CentOS6.5 编译安装lnmp环境
Dec 21 PHP
php使用fputcsv()函数csv文件读写数据的方法
Jan 06 PHP
php绘图之在图片上写中文和英文的方法
Jan 24 PHP
PHP模拟asp中response类实现方法
Aug 08 PHP
求帮忙修改个php curl模拟post请求内容后并下载文件的解决思路
Sep 20 PHP
PHP去除空数组且数组键名重置的讲解
Feb 28 PHP
php数值计算num类简单操作示例
May 15 PHP
phpmailer在服务器上不能正常发送邮件的解决办法
Jul 08 #PHP
php去掉URL网址中带有PHPSESSID的配置方法
Jul 08 #PHP
PHP大批量插入数据库的3种方法和速度对比
Jul 08 #PHP
php发送get、post请求的6种方法简明总结
Jul 08 #PHP
PHP中对各种加密算法、Hash算法的速度测试对比代码
Jul 08 #PHP
微信公众平台天气预报功能开发
Jul 06 #PHP
最常用的8款PHP调试工具
Jul 06 #PHP
You might like
JoshChen_php新手进阶高手不可或缺的规范介绍
2013/08/16 PHP
yiic命令时提示“php.exe”不是内部或外部命令的解决方法
2014/12/18 PHP
php将图片文件转换成二进制输出的方法
2015/06/10 PHP
thinkPHP利用ajax异步上传图片并显示、删除的示例
2018/09/26 PHP
javascript的事件描述
2006/09/08 Javascript
javascript 原型模式实现OOP的再研究
2009/04/09 Javascript
对字符串进行HTML编码和解码的JavaScript函数
2010/02/01 Javascript
JavaScript中的几个关键概念的理解-原型链的构建
2011/05/12 Javascript
深入浅出理解javaScript原型链
2015/05/09 Javascript
js操作XML文件的实现方法兼容IE与FireFox
2016/06/25 Javascript
详解vue开发中调用微信jssdk的问题
2019/04/16 Javascript
vue中touch和click共存的解决方式
2020/07/28 Javascript
解决vue+elementui项目打包后样式变化问题
2020/08/03 Javascript
原生JS实现多条件筛选
2020/08/19 Javascript
Vue router安装及使用方法解析
2020/12/02 Vue.js
vue3.0封装轮播图组件的步骤
2021/03/04 Vue.js
[05:49]DOTA2-DPC中国联赛 正赛 Elephant vs LBZS 选手采访
2021/03/11 DOTA
python Django模板的使用方法
2016/01/14 Python
用 Python 连接 MySQL 的几种方式详解
2018/04/04 Python
python 移除字符串尾部的数字方法
2018/07/17 Python
Appium Python自动化测试之环境搭建的步骤
2019/01/23 Python
python实现猜拳小游戏
2020/04/05 Python
pytorch: Parameter 的数据结构实例
2019/12/31 Python
浅谈多卡服务器下隐藏部分 GPU 和 TensorFlow 的显存使用设置
2020/06/30 Python
Pycharm及python安装详细教程(图解)
2020/07/31 Python
基于CSS3 animation动画属性实现轮播图效果
2017/09/12 HTML / CSS
项目总经理岗位职责
2014/02/14 职场文书
全国优秀辅导员事迹材料
2014/05/14 职场文书
中学生教师节演讲稿
2014/09/03 职场文书
新年寄语2016
2015/08/17 职场文书
Nginx tp3.2.3 404问题解决方案
2021/03/31 Servers
CocosCreator ScrollView优化系列之分帧加载
2021/04/14 Python
vue完美实现el-table列宽自适应
2021/05/08 Vue.js
Python实现简单的俄罗斯方块游戏
2021/09/25 Python
Mybatis是这样防止sql注入的
2021/12/06 Java/Android
Windows server 2012搭建FTP服务器
2022/04/29 Servers