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 zend解密软件绿色版测试可用
Apr 14 PHP
PHP高手需要要掌握的知识点
Aug 21 PHP
跟我学Laravel之路由
Oct 15 PHP
PHP中SimpleXML函数用法分析
Nov 26 PHP
php读取csv文件并输出的方法
Mar 14 PHP
PHP实现链式操作的核心思想
Jun 23 PHP
PHP操作FTP类 (上传、下载、移动、创建等)
Mar 31 PHP
基于PHP实现商品成交时发送短信功能
May 11 PHP
php array_reverse 以相反的顺序返回数组实例代码
Apr 11 PHP
源码分析 Laravel 重复执行同一个队列任务的原因
Dec 25 PHP
在Laravel中使用DataTables插件的方法
May 29 PHP
Laravel 默认邮箱登录改成用户名登录的实现方法
Aug 12 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
浅析PHP递归函数返回值使用方法
2013/02/18 PHP
php中switch与ifelse的效率区别及适用情况分析
2015/02/12 PHP
PHP中使用Memache作为进程锁的操作类分享
2015/03/30 PHP
PHP获取Exif缩略图的方法
2015/07/13 PHP
PHP新特性详解之命名空间、性状与生成器
2017/07/18 PHP
jquery 单引号和双引号的区别及使用注意
2013/07/31 Javascript
JavaScript实现将xml转换成html table表格的方法
2015/04/17 Javascript
jQuery实现的经典滑动门效果
2015/09/22 Javascript
JS实现的页面自定义滚动条效果
2015/10/26 Javascript
React.js入门学习第一篇
2016/03/30 Javascript
原生js实现对Ajax的封装(仿jquery)
2017/01/22 Javascript
jQuery实现的简单在线计算器功能
2017/05/11 jQuery
关于Vue的路由权限管理的示例代码
2018/03/06 Javascript
react以create-react-app为基础创建项目
2018/03/14 Javascript
Vue三层嵌套路由的示例代码
2018/05/05 Javascript
vue 中使用 watch 出现了如下的报错的原因分析
2019/05/21 Javascript
Vue快速实现通用表单验证功能
2019/12/05 Javascript
[04:04]DOTA2亚洲邀请赛比赛场馆&酒店全攻略
2017/03/23 DOTA
[01:45:05]VGJ.T vs Newbee Supermajor 败者组 BO3 第二场 6.6
2018/06/07 DOTA
Python时间戳与时间字符串互相转换实例代码
2013/11/28 Python
Queue 实现生产者消费者模型(实例讲解)
2017/11/13 Python
python中使用print输出中文的方法
2018/07/16 Python
python+mysql实现教务管理系统
2019/02/20 Python
python数组循环处理方法
2019/08/26 Python
Python 将json序列化后的字符串转换成字典(推荐)
2020/01/06 Python
浅谈keras使用中val_acc和acc值不同步的思考
2020/06/18 Python
CSS3 选择器 伪类选择器介绍
2012/01/21 HTML / CSS
HTML5的download属性详细介绍和使用实例
2014/04/23 HTML / CSS
html5 实现客户端验证上传文件的大小(简单实例)
2016/05/15 HTML / CSS
教师师德教育的自我评价
2013/10/31 职场文书
幼儿园中秋节活动方案
2014/02/06 职场文书
办公室主任岗位承诺书
2014/05/29 职场文书
2014年学生会干事工作总结
2014/11/07 职场文书
护理专业自我评价
2015/03/11 职场文书
2016猴年春节问候语
2015/11/11 职场文书
导游词之唐山景点
2019/12/18 职场文书