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 中的str_replace 函数总结
Apr 27 PHP
PHP 手机归属地查询 api
Feb 08 PHP
php中获取远程客户端的真实ip地址的方法
Aug 03 PHP
phpmyadmin显示utf8_general_ci中文乱码的问题终级篇
Apr 08 PHP
PHP中鲜为人知的10个函数
Feb 28 PHP
php微信公众开发之获取周边酒店信息的方法
Dec 22 PHP
php控制文件下载速度的方法
Mar 24 PHP
PHP给文字内容中的关键字进行套红处理
Apr 12 PHP
CI框架AR操作(数组形式)实现插入多条sql数据的方法
May 18 PHP
PHP入门教程之日期与时间操作技巧总结(格式化,验证,获取,转换,计算等)
Sep 11 PHP
php实现等比例不失真缩放上传图片的方法
Nov 14 PHP
PHP守护进程化在C和PHP环境下的实现
Nov 21 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
mysql 的 like 问题,超强毕杀记!!!
2007/01/18 PHP
调整优化您的LAMP应用程序的5种简单方法
2011/06/26 PHP
php版微信公众平台接口开发之智能回复开发教程
2016/09/22 PHP
使用正则去除php代码中的注释方法
2016/11/03 PHP
一个可以随意添加多个序列的tag函数
2009/07/21 Javascript
jQuery库与其他JS库冲突的解决办法
2010/02/07 Javascript
javascript 全选与全取消功能的实现代码
2012/12/23 Javascript
用js实现控件的隐藏及style.visibility的使用
2013/06/14 Javascript
JS中的form.submit()不能提交表单的错误原因
2014/10/08 Javascript
JavaScript模拟深蓝vs卡斯帕罗夫的国际象棋对局示例
2015/04/22 Javascript
js生成验证码并直接在前端判断
2015/05/15 Javascript
jQuery+ajax实现无刷新级联菜单示例
2015/05/21 Javascript
jquery插件splitScren实现页面分屏切换模板特效
2015/06/16 Javascript
JavaScript 模块的循环加载实现方法
2015/12/13 Javascript
Angularjs中如何使用filterFilter函数过滤
2016/02/06 Javascript
jQuery实现鼠标经过像翻页和描点链接效果
2016/08/08 Javascript
AngularJS实践之使用NgModelController进行数据绑定
2016/10/08 Javascript
js中编码函数:escape,encodeURI与encodeURIComponent详解
2017/03/21 Javascript
javascript 中null和undefined区分和比较
2017/04/19 Javascript
JavaScript使用FileReader实现图片上传预览效果
2020/03/27 Javascript
基于JavaScript 性能优化技巧心得(分享)
2017/12/11 Javascript
js中this对象用法分析
2018/01/05 Javascript
React中如何引入Angular组件详解
2018/08/09 Javascript
利用jsonp解决js读取本地json跨域的问题
2018/12/11 Javascript
vue中实现动态生成二维码的方法
2020/02/21 Javascript
[02:37]2018DOTA2亚洲邀请赛赛前采访 VP.no[o]ne心中最强SOLO是谁
2018/04/04 DOTA
Python生成随机MAC地址
2015/03/10 Python
Python爬取网易云音乐上评论火爆的歌曲
2017/01/19 Python
使用Python写一个量化股票提醒系统
2018/08/22 Python
Python collections.defaultdict模块用法详解
2020/06/18 Python
浅谈Keras中shuffle和validation_split的顺序
2020/06/19 Python
BudgetAir印度:预订航班、酒店和汽车租赁
2019/07/07 全球购物
大一新生军训时的自我评价分享
2013/12/05 职场文书
公司周年庆典邀请函
2014/01/12 职场文书
优秀毕业自我鉴定
2014/02/15 职场文书
python实现剪贴板的操作
2021/07/01 Python