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 相关文章推荐
截获网站title标签之家内容的例子
Oct 09 PHP
PHP 中执行排序与 MySQL 中排序
Apr 21 PHP
PHP 输出URL的快捷方式示例代码
Sep 22 PHP
使用php方法curl抓取AJAX异步内容思路分析及代码分享
Aug 25 PHP
PHP获取文件夹内文件数的方法
Mar 12 PHP
php显示指定目录下子目录的方法
Mar 20 PHP
分享自定义的几个PHP功能函数
Apr 15 PHP
php实现的RSS生成类实例
Apr 23 PHP
PHP代码实现表单数据验证类
Jul 28 PHP
THINKPHP在添加数据的时候获取主键id的值方法
Apr 03 PHP
Laravel框架路由管理简单示例
May 07 PHP
php引用和拷贝的区别知识点总结
Sep 23 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里面的抽象类
2010/01/28 PHP
php中session退出登陆问题
2014/02/27 PHP
PHP中SESSION的注销与清除
2015/04/16 PHP
PHP中Cookie的使用详解(简单易懂)
2017/04/28 PHP
基于thinkphp5框架实现微信小程序支付 退款 订单查询 退款查询操作
2020/08/17 PHP
鼠标移入移出事件改变图片的分辨率的两种方法
2013/12/17 Javascript
js重写alert控件(适合学习js的新手朋友)
2014/08/24 Javascript
JS获取时间的方法
2015/01/21 Javascript
jQuery模拟原生态App上拉刷新下拉加载更多页面及原理
2015/08/10 Javascript
jQuery插件Validate实现自定义校验结果样式
2016/01/18 Javascript
实现React单页应用的方法详解
2016/08/02 Javascript
CentOS 安装NodeJS V8.0.0的方法
2017/06/15 NodeJs
JS 60秒后重新发送验证码的实例讲解
2017/07/26 Javascript
python爬取安居客二手房网站数据(实例讲解)
2017/10/19 Javascript
layui表格内容溢出的解决方法
2019/09/06 Javascript
JavaScript仿京东秒杀倒计时
2020/03/17 Javascript
js实现贪吃蛇游戏(简易版)
2020/09/29 Javascript
JS检测浏览器开发者工具是否打开的方法详解
2020/10/02 Javascript
jQuery实现鼠标拖动图片功能
2021/03/04 jQuery
[06:25]第二届DOTA2亚洲邀请赛主赛事第二天比赛集锦.mp4
2017/04/03 DOTA
Python实现查找系统盘中需要找的字符
2015/07/14 Python
python 输出所有大小写字母的方法
2019/01/02 Python
Django模板标签中url使用详解(url跳转到指定页面)
2020/03/19 Python
美国面料纺织品商城:Fabric.com
2017/06/28 全球购物
Optimalprint加拿大:在线打印服务
2020/04/03 全球购物
本科生个人求职自荐信
2013/09/26 职场文书
理工科学生的自我评价
2013/12/15 职场文书
护理专业学生职业生涯规划范文
2014/03/11 职场文书
道路施工安全责任书
2014/07/24 职场文书
2015年团队工作总结范文
2015/05/04 职场文书
中学推普周活动总结
2015/05/07 职场文书
退休欢送会致辞
2015/07/31 职场文书
观看《筑梦中国》纪录片心得体会
2016/01/18 职场文书
全家福照片寄语怎么写?
2019/04/02 职场文书
给原生html中添加水印遮罩层的实现示例
2021/04/02 Javascript
90后经典动画片排行:《数码宝贝》第二,《小鲤鱼历险记》在榜
2022/03/18 日漫