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版)
Oct 09 PHP
php下intval()和(int)转换使用与区别
Jul 18 PHP
封装一个PDO数据库操作类代码
Sep 09 PHP
php模拟asp中的XmlHttpRequest实现http请求的代码
Mar 24 PHP
php适配器模式介绍
Aug 14 PHP
php ios推送(代码)
Jul 01 PHP
详解php设置session(过期、失效、有效期)
Nov 12 PHP
修改PHP脚本使WordPress拦截垃圾评论的方法示例
Dec 10 PHP
解析WordPress中控制用户登陆和判断用户登陆的PHP函数
Mar 01 PHP
php实现当前页面点击下载文件的简单方法
Sep 22 PHP
详解php中的implements 使用
Jun 13 PHP
Thinkphp5.0框架使用模型Model的获取器、修改器、软删除数据操作示例
Oct 11 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得到某段时间区间的时间戳 php定时任务
2012/04/12 PHP
php实现约瑟夫问题的方法小结
2015/03/23 PHP
PHP中把数据库查询结果输出为json格式简单实例
2015/04/09 PHP
PHP实现的激活用户注册验证邮箱功能示例
2017/06/06 PHP
Javascript Math ceil()、floor()、round()三个函数的区别
2010/03/09 Javascript
JavaScript之appendChild、insertBefore和insertAfter使用说明
2010/12/30 Javascript
js实现点击注册按钮开始读秒倒计时的小例子
2013/05/11 Javascript
解决jquery中美元符号命名冲突问题
2014/01/08 Javascript
浅谈Nodejs观察者模式
2015/10/13 NodeJs
解决JS请求服务器gbk文件乱码的问题
2015/10/16 Javascript
JS控制静态页面之间传递参数获取参数并应用的简单实例
2016/08/10 Javascript
详解AngularJS中的表单验证(推荐)
2016/11/17 Javascript
jQuery实现验证码功能
2017/03/17 Javascript
axios取消请求的实践记录分享
2018/09/26 Javascript
基于vue.js组件实现分页效果
2018/12/29 Javascript
JS求1到任意数之间的所有质数的方法详解
2019/05/20 Javascript
Bootstrap简单实用的表单验证插件BootstrapValidator用法实例详解
2020/03/29 Javascript
vue基于better-scroll仿京东分类列表
2020/06/30 Javascript
vue中是怎样监听数组变化的
2020/10/24 Javascript
[00:08]DOTA2勇士令状等级奖励“天外飞星”
2019/05/24 DOTA
Python获取远程文件大小的函数代码分享
2014/05/13 Python
Python 2/3下处理cjk编码的zip文件的方法
2019/04/26 Python
python mongo 向数据中的数组类型新增数据操作
2020/12/05 Python
工程测量与监理专业应届生求职信
2013/11/27 职场文书
大堂副理的岗位职责范文
2014/02/17 职场文书
《老山界》教学反思
2014/04/08 职场文书
入党综合考察材料
2014/06/02 职场文书
测控技术自荐信
2014/06/05 职场文书
涨价通知怎么写
2015/04/23 职场文书
2015年反洗钱工作总结
2015/04/25 职场文书
特此通知格式
2015/04/27 职场文书
校车司机安全责任书
2015/05/11 职场文书
消防安全主题班会
2015/08/12 职场文书
奖学金申请个人主要事迹材料
2015/11/04 职场文书
《给予树》教学反思
2016/03/03 职场文书
Mysql数据库事务的脏读幻读及不可重复读详解
2022/05/30 MySQL