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将向Java靠拢
Oct 09 PHP
Array of country list in PHP with Zend Framework
Oct 17 PHP
PHP入门经历和学习过程分享
Apr 11 PHP
php结合js实现点击超链接执行删除确认操作
Oct 31 PHP
PHP获取一年中每个星期的开始和结束日期的方法
Feb 12 PHP
PHP连接MySQL数据的操作要点
Mar 20 PHP
php动态生成版权所有信息的方法
Mar 24 PHP
php导出中文内容excel文件类实例
Jul 06 PHP
php给图片加文字水印
Jul 31 PHP
PHP-FPM之Chroot执行环境详解
Aug 03 PHP
PHP实现获取毫秒时间戳的方法【使用microtime()函数】
Mar 01 PHP
thinkphp5 路由分发原理
Mar 18 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
windwos下使用php连接oracle数据库的过程分享
2014/05/26 PHP
PHP设计模式之工厂模式(Factory Pattern)的讲解
2019/03/21 PHP
零基础php编程好学吗
2019/10/11 PHP
js 字符串操作函数
2009/07/25 Javascript
jQuery 1.5 源码解读 面向中高阶JSER
2011/04/05 Javascript
jQuery动态显示和隐藏datagrid中的某一列的方法
2013/12/11 Javascript
网页右下角弹出窗体实现代码
2014/06/05 Javascript
JQuery中两个ul标签的li互相移动实现方法
2015/05/18 Javascript
初步了解javascript面向对象
2015/11/09 Javascript
BootStrap和jQuery相结合实现可编辑表格
2016/04/21 Javascript
JS简单生成两个数字之间随机数的方法
2016/08/03 Javascript
js实现文字无缝向上滚动
2017/02/16 Javascript
JS字符串统计操作示例【遍历,截取,输出,计算】
2017/03/27 Javascript
原生javascript实现分页效果
2017/04/21 Javascript
vue中实现先请求数据再渲染dom分享
2018/03/17 Javascript
VUE+Element UI实现简单的表格行内编辑效果的示例的代码
2018/10/31 Javascript
JavaScript实现滑动门效果
2020/01/18 Javascript
vue-cli点击实现全屏功能
2020/03/07 Javascript
Vue自定义多选组件使用详解
2020/09/08 Javascript
Python 文件和输入输出小结
2013/10/09 Python
itchat接口使用示例
2017/10/23 Python
python简单实例训练(21~30)
2017/11/15 Python
Python实现读取SQLServer数据并插入到MongoDB数据库的方法示例
2018/06/09 Python
python 模拟创建seafile 目录操作示例
2019/09/26 Python
Flask框架路由和视图用法实例分析
2019/11/07 Python
Python猴子补丁Monkey Patch用法实例解析
2020/03/23 Python
简述 Python 的类和对象
2020/08/21 Python
Python pip 常用命令汇总
2020/10/19 Python
Ibatis如何调用存储过程
2015/05/15 面试题
大专毕业生简历的自我评价
2013/10/20 职场文书
企划专员岗位职责
2013/12/09 职场文书
策划总监岗位职责
2014/02/16 职场文书
经典的毕业生自荐信范文
2014/04/14 职场文书
幼儿园教师的自我评价范文
2014/09/17 职场文书
个人思想政治总结
2015/03/05 职场文书
中标通知书
2015/04/17 职场文书