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实现异步调用方法研究与分享
Oct 27 PHP
解析:php调用MsSQL存储过程使用内置RETVAL获取过程中的return值
Jul 03 PHP
使用PHP Socket写的POP3类
Oct 30 PHP
PHP Warning: Module 'modulename' already loaded in问题解决办法
Mar 16 PHP
PHP+Mysql+jQuery查询和列表框选择操作实例讲解
Oct 22 PHP
再推荐十款免费的php开发工具
Nov 09 PHP
CodeIgniter配置之config.php用法实例分析
Jan 19 PHP
Symfony2学习笔记之系统路由详解
Mar 17 PHP
PHP基于XMLWriter操作xml的方法分析
Jul 17 PHP
PHP回调函数概念与用法实例分析
Nov 03 PHP
thinkphp框架无限级栏目的排序功能实现方法示例
Mar 29 PHP
PHP变量的作用范围实例讲解
Dec 22 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
基于preg_match_all采集后数据处理的一点心得笔记(编码转换和正则匹配)
2014/01/31 PHP
jquery实现用户信息修改验证输入方法汇总
2015/07/18 Javascript
谈谈encodeURI和encodeURIComponent以及escape的区别与应用
2015/11/24 Javascript
jQuery焦点图插件SaySlide
2015/12/21 Javascript
jQuery基于$.ajax设置移动端click超时处理方法
2016/05/14 Javascript
纯JavaScript手写图片轮播代码
2016/10/20 Javascript
Node.js测试中的Mock文件系统详解
2016/11/21 Javascript
使用angular帮你实现拖拽的示例
2017/07/05 Javascript
jQuery niceScroll滚动条错位问题的解决方法
2018/02/03 jQuery
详解js中Array的方法及技巧
2018/09/12 Javascript
微信小程序实现展示评分结果功能
2019/02/15 Javascript
微信小程序框架的页面布局代码
2019/08/17 Javascript
npm qs模块使用详解
2020/02/07 Javascript
微信小程序scroll-view点击项自动居中效果的实现
2020/03/25 Javascript
微信小程序的引导页实现代码
2020/06/24 Javascript
vue实现自定义多选按钮
2020/07/16 Javascript
[02:03]DOTA2亚洲邀请赛 HGT战队出场宣传片
2015/02/07 DOTA
python实现带验证码网站的自动登陆实现代码
2015/01/12 Python
Python中 map()函数的用法详解
2018/07/10 Python
Python turtle绘画象棋棋盘
2019/08/21 Python
pandas条件组合筛选和按范围筛选的示例代码
2019/08/26 Python
PyCharm 2019.3发布增加了新功能一览
2019/12/08 Python
OpenCV+python实现实时目标检测功能
2020/06/24 Python
CSS3+HTML5+JS 实现一个块的收缩与展开动画效果
2020/11/17 HTML / CSS
HTML5利用约束验证API来检查表单的输入数据的代码实例
2016/12/20 HTML / CSS
印尼综合在线预订网站:Tiket.com(机票、酒店、火车、租车和娱乐)
2018/10/11 全球购物
英文翻译的自我评价语句
2013/10/04 职场文书
电子商务毕业生求职信
2013/11/10 职场文书
服装设计专业自荐书范文
2013/12/30 职场文书
应用艺术专业个人的自我评价
2014/01/03 职场文书
初三物理教学反思
2014/01/21 职场文书
出生公证委托书
2014/04/03 职场文书
大型营销活动计划书
2014/04/28 职场文书
预备党员入党感言
2015/08/01 职场文书
导游词之江苏同里古镇
2019/11/18 职场文书
Java异常处理try catch的基本用法
2021/12/06 Java/Android