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 取得瑞年与平年的天数的代码
Aug 10 PHP
PHP 杂谈《重构-改善既有代码的设计》之三 重新组织数据
Apr 09 PHP
php中多维数组按指定value排序的实现代码
Aug 19 PHP
PHP中使用json数据格式定义字面量对象的方法
Aug 20 PHP
PHP多个文件上传到服务器实例
Oct 29 PHP
php实现递归的三种基本方式
Jul 04 PHP
CodeIgniter多语言实现方法详解
Jan 20 PHP
PHP错误机制知识汇总
Mar 24 PHP
PHP简单实现文本计数器的方法
Apr 28 PHP
PHP用continue跳过本次循环中剩余代码的注意点
Jun 27 PHP
Symfony查询方法实例小结
Jun 28 PHP
PHP实现的pdo连接数据库并插入数据功能简单示例
Mar 30 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
用phpmyadmin更改mysql5.0登录密码
2008/03/25 PHP
详解PHP对数组的定义以及数组的创建方法
2015/11/27 PHP
推荐自用 Javascript 缩图函数 (onDOMLoaded)……
2007/10/23 Javascript
JS学习之一个简易的日历控件
2010/03/24 Javascript
jQuery EasyUI NumberBox(数字框)的用法
2010/07/08 Javascript
基于JQuery实现异步刷新的代码(转载)
2011/03/29 Javascript
js自定义方法通过隐藏iframe实现文件下载
2013/02/21 Javascript
使用js获取地址栏中传递的值
2013/07/02 Javascript
Jquery实现瀑布流布局(备有详细注释)
2015/07/31 Javascript
详解Jquery 遍历数组之$().each方法与$.each()方法介绍
2017/01/09 Javascript
JavaScript mixin实现多继承的方法详解
2017/03/30 Javascript
vue.js使用代理和使用Nginx来解决跨域的问题
2018/02/03 Javascript
默认浏览器设置及vue自动打开页面的方法
2018/09/21 Javascript
vue权限问题的完美解决方案
2019/05/08 Javascript
vue开发chrome插件,实现获取界面数据和保存到数据库功能
2020/12/01 Vue.js
[02:41]2015国际邀请赛中国区预选赛观战指南
2015/05/20 DOTA
python通过exifread模块获得图片exif信息的方法
2015/03/16 Python
django接入新浪微博OAuth的方法
2015/06/29 Python
Python实现图片转字符画的示例代码
2017/08/21 Python
从CentOS安装完成到生成词云python的实例
2017/12/01 Python
Django视图和URL配置详解
2018/01/31 Python
Python 新建文件夹与复制文件夹内所有内容的方法
2018/10/27 Python
Python图像处理实现两幅图像合成一幅图像的方法【测试可用】
2019/01/04 Python
python实现H2O中的随机森林算法介绍及其项目实战
2019/08/29 Python
使用已经得到的keras模型识别自己手写的数字方式
2020/06/29 Python
Python结合百度语音识别实现实时翻译软件的实现
2021/01/18 Python
HTML5 Canvas 起步(1) - 基本概念
2009/05/12 HTML / CSS
如何用canvas实现在线签名的示例代码
2018/07/10 HTML / CSS
网络程序员自荐信
2014/01/25 职场文书
应届毕业生自荐信
2014/05/28 职场文书
土建工程师岗位职责
2014/06/10 职场文书
优秀护士事迹材料
2014/12/25 职场文书
学校德育工作总结2015
2015/05/11 职场文书
幼儿园托班教育随笔
2015/08/14 职场文书
用Python实现屏幕截图详解
2022/01/22 Python
Redis官方可视化工具RedisInsight安装使用教程
2022/04/19 Redis