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 相关文章推荐
Content-type 的说明
Oct 09 PHP
PHP获取用户的浏览器与操作系统信息的代码
Sep 04 PHP
PHP把空格、换行符、中文逗号等替换成英文逗号的正则表达式
May 04 PHP
php利用事务处理转账问题
Apr 22 PHP
PHP之浮点数计算比较以及取整数不准确的解决办法
Jul 29 PHP
详解WordPress中创建和添加过滤器的相关PHP函数
Dec 29 PHP
HTML中嵌入PHP的简单方法
Feb 16 PHP
PHP安装GeoIP扩展根据IP获取地理位置及计算距离的方法
Jul 01 PHP
centos 7.2下搭建LNMP环境教程
Nov 20 PHP
浅谈PHP命令执行php文件需要注意的问题
Dec 16 PHP
PHP实现超简单的SSL加密解密、验证及签名的方法示例
Aug 28 PHP
PHP实现数据四舍五入的方法小结【4种方法】
Mar 27 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 Mysql日期和时间函数集合
2007/11/16 PHP
php查看请求头信息获取远程图片大小的方法分享
2013/12/25 PHP
php实现源代码加密的方法
2015/07/11 PHP
js代码实现微博导航栏
2015/07/30 PHP
Windows下php+mysql5.7配置教程
2017/05/16 PHP
JSON 编辑器实现代码
2009/12/06 Javascript
自定义jquery模态窗口插件无法在顶层窗口显示问题
2014/05/29 Javascript
JavaScript中使用Object.create()创建对象介绍
2014/12/30 Javascript
总结十个Angular.js由浅入深的面试问题
2016/08/26 Javascript
JS 验证密码 不能为空,必须含有数字、字母、特殊字符,长度在8-12位
2017/06/21 Javascript
详解Vuejs2.0 如何利用proxyTable实现跨域请求
2017/08/03 Javascript
JavaScript常见继承模式实例小结
2019/01/11 Javascript
Angular脚手架开发的实现步骤
2019/04/09 Javascript
ES6 Symbol数据类型的应用实例分析
2019/06/26 Javascript
jquery树形插件zTree高级使用详解
2019/08/16 jQuery
基于原生js实现九宫格算法代码实例
2020/07/03 Javascript
[00:06]Yes,it worked!小卡尔成功穿越时空加入战场!
2019/07/20 DOTA
Python subprocess模块学习总结
2014/03/13 Python
Python 字典dict使用介绍
2014/11/30 Python
创建Django项目图文实例详解
2019/06/06 Python
python GUI库图形界面开发之pyinstaller打包python程序为exe安装文件
2020/02/26 Python
Python在centos7.6上安装python3.9的详细教程(默认python版本为2.7.5)
2020/10/15 Python
Django restful framework生成API文档过程详解
2020/11/12 Python
Python爬虫之Selenium多窗口切换的实现
2020/12/04 Python
美国旅游网站:Tours4Fun
2017/02/17 全球购物
西班牙最大的在线滑板和街头服饰商店:Fillow.net
2019/04/15 全球购物
证婚人经典证婚词
2014/01/09 职场文书
十佳家长事迹材料
2014/08/26 职场文书
2014国庆节餐厅促销活动策划方案
2014/09/16 职场文书
学生上课看漫画的检讨书
2014/09/26 职场文书
大三学年自我鉴定范文(3篇)
2014/09/28 职场文书
上课迟到检讨书300字
2014/10/15 职场文书
谢师宴邀请函
2015/02/02 职场文书
辞职离别感言
2015/08/04 职场文书
四则混合运算教学反思
2016/02/23 职场文书
Win11 Beta 预览版 22621.575 和 22622.575更新补丁KB5016694发布(附更新内容大全)
2022/08/14 数码科技