PHP中的插件机制原理和实例

PHP项目中很多用到插件的地方,更尤其是基础程序写成之后很多功能由第三方完善开发的时候,更能用到插件机制,现在说一下插件的实现。特点是无论你是否激活,都不影响主程序的运行,即使是删除也不会影响。

从一个插件安装到运行过程的角度来说,主要是三个步骤:

1.插件安装(把插件信息收集进行采集和记忆的过程,比如放到数据库中或者XML中)

2.插件激活(打开插件,让监听插件的地方开始进行调用)

3.插件运行(插件功能的实现)

从一个插件的运行上来说主要以下几点:

1.插件的动态监听和加载(插件的信息获取)

2.插件的动态触发(插件的运行)

一个完善的插件系统主要包括以下:

1.插件安装及卸载

2.插件打开与关闭

3.插件信息获取

4.插件调度(插件经理)

5.插件主体

在程序的编写上主要实现以下:

1.插件的注册和初始化

2.判断激活条件

3.钩子激活

4.运行插件

实例代码:

<?php
/**
* PluginManager Class
*
* 插件机制的实现核心类
*
* @link http://www.jb51.net/
*/
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    http://www.jb51.net/
 */
/**
 *需要注意的几个默认规则:
 *  1. 本插件类的文件名必须是action
 *  2. 插件类的名称必须是{插件名_actions}
 */
class DEMO_actions
{
  //解析函数的参数是pluginManager的引用
  function __construct(&$pluginManager)
  {
    //注册这个插件
    //第一个参数是钩子的名称
    //第二个参数是pluginManager的引用
    //第三个是插件所执行的方法
    $pluginManager->register('demo', $this, 'say_hello');
  }

  function say_hello()
  {
    echo 'Hello World';
  }
}
(0)

相关推荐

  • 浅析php中常量,变量的作用域和生存周期

    在PHP脚本中变量主要有:内置超级全局变量,一般的变量,常量,全局变量,静态变量等等,我们在使用它们的时候除了要正确地知道它们的语法以外,更重要的是,我们要知道它们在本质上的区别与联系-即它们的作用域的问题. 1.内置超级全局变量可以在脚本的任何地方使用和可见.即是说,如果我们在一个PHP页面中改变了其中的一个值,那么在其他PHP页面中使用时,它的值也会发生改变. 2.常量一旦被声明将可以在全局可见,也就是说,它们可以函数内外使用,但是这仅仅限于一个页面之中(包含我们通过include和incl

  • 深入理解PHP原理之执行周期分析

    本文讲述了PHP原理之执行周期.分享给大家供大家参考,具体如下: PHP的执行周期,从最初我们编写的PHP脚本->到最后脚本被执行->得到执行结果,这个过程,其实可以分为如下几个阶段: 首先,Zend Engine(ZE),调用词法分析 器(Lex生成的,源文件在 Zend/zend_language_sanner.l), 将我们要执行的PHP源文件,去掉空格 ,注释,分割成一个一个的token. 然后,ZE会将得到的token forward给语法分析 器(yacc生成, 源文件在 Zend

  • 深入理解PHP原理之Session Gc的一个小概率Notice

    如果在ubuntu/Debian下, 采用apt安装的PHP, 那么在使用Session的时候, 就可能会有小概率遇到这个提示. 复制代码 代码如下: PHP Notice: session_start(): ps_files_cleanup_dir: opendir(/var/lib/php5) failed: Permission denied (13) in /home/laruence/www/htdocs/index.php on line 22 这是因为, 在PHP中, 如果使用fi

  • PHP的运行机制与原理(底层)

    说到php的运行机制还要先给大家介绍php的模块,PHP总共有三个模块:内核.Zend引擎.以及扩展层:PHP内核用来处理请求.文件流.错误处理等相关操作:Zend引擎(ZE)用以将源文件转换成机器语言,然后在虚拟机上运行它:扩展层是一组函数.类库和流,PHP使用它们来执行一些特定的操作.比如,我们需要mysql扩展来连接MySQL数据库:当ZE执行程序时可能会需要连接若干扩展,这时ZE将控制权交给扩展,等处理完特定任务后再返还: 最后,ZE将程序运行结果返回给PHP内核,它再将结果传送给SAP

  • 关于PHP5 Session生命周期介绍

    它是通过 Session ID 来判断的,什么是 Session ID,就是那个 Session 文件的文件名,Session ID 是随机生成的,因此能保证唯一性和随机性,确保Session 的安全.一般如果没有设置 Session 的生存周期,则 Session ID 存储在内存中,关闭浏览器后该 ID 自动注销,重新请求该页面后,重新注册一个 Session ID. 如果客户端没有禁用 Cookie,则 Cookie 在启动 Session 会话的时候扮演的是存储 Session ID 和

  • 深入理解PHP原理之异常机制

    PHP的异常机制的原理是什么? 在PHP每一个可独立执行的op array最后的ZEND_HANDLE_EXCEPTION是用来干什么呢? 让我们从一个问题说起, 上周的时候, blue5tar提了一个问题:"对于下面的代码, onError明明执行了, 但是onException却没有执行, 为什么?". 复制代码 代码如下: <?php function onError($errCode, $errMesg, $errFile, $errLine) { echo "

  • PHP内核探索:哈希表碰撞攻击原理

    下面通过图文并茂的方式给大家展示PHP内核探索:哈希表碰撞攻击原理. 最近哈希表碰撞攻击(Hashtable collisions as DOS attack)的话题不断被提起,各种语言纷纷中招.本文结合PHP内核源码,聊一聊这种攻击的原理及实现.  哈希表碰撞攻击的基本原理 哈希表是一种查找效率极高的数据结构,很多语言都在内部实现了哈希表.PHP中的哈希表是一种极为重要的数据结构,不但用于表示Array数据类型,还在Zend虚拟机内部用于存储上下文环境信息(执行上下文的变量及函数均使用哈希表结

  • 深入理解PHP之OpCode原理详解

    本文实例讲述了PHP中OpCode的原理.分享给大家供大家参考,具体如下: OpCode是一种PHP脚本编译后的中间语言,就像Java的ByteCode,或者.NET的MSL. 此文主要基于< Understanding OPcode>和 网络,根据个人的理解和修改,特记录下来 : PHP代码: <?php echo "Hello World"; $a = 1 + 1; echo $a; ?> PHP执行这段代码会经过如下4个步骤: 1. Scanning (L

  • 理解php原理的opcodes(操作码)

    Opcondes是一种php脚本编译后的中间语言,就像Java的Byte Code,或者.NET 的MSL .(都没了解过~) 举个文中的例子 复制代码 代码如下: <?php echo "Hello World"; $a = 1 + 1; echo $a; ?> PHP执行这段代码会经过如下4个步骤(确切的来说,应该是PHP的语言引擎Zend) 复制代码 代码如下: 1.Scanning(Lexing) (扫描),将PHP代码转换为语言片段(Tokens) 2.Parsi

  • PHP原理之异常机制深入分析

    PHP的异常机制的原理是什么? 在PHP每一个可独立执行的op array最后的ZEND_HANDLE_EXCEPTION是用来干什么呢? 让我们从一个问题说起, 上周的时候, blue5tar提了一个问题:"对于下面的代码, onError明明执行了, 但是onException却没有执行, 为什么?". 复制代码 代码如下: <?php function onError($errCode, $errMesg, $errFile, $errLine) { echo "

  • 深入理解PHP原理之错误抑制与内嵌HTML分析

    PHP提供了一个错误抑制符'@', 它是通过什么方式来阻止错误输出呢? 我又该在什么时候使用它呢? 这是这俩天一些网友提到的共同问题, 今天就索性整体回答下, 备后来人翻阅. PHP文件内嵌HTML的处理方式 在PHP中, 所有在标签外的字符, 在词法分析过程中, 都会翻译成T_INLINE_HTML token, 在语法分析的时候, 所有的T_INLIE_HTML都会被分配ZEND_ECHO输出. 也就是说: 复制代码 代码如下: <?php while($con) { ?> laruenc

  • PHP STRING 陷阱原理说明

    A string is series of characters. String access and modification by character Characters within strings may be accessed and modified by specifying the zero-based offset of the desired character after the string using square array brackets, as in $str

  • 修改Zend引擎实现PHP源码加密的原理及实践

    一.基本原理 考虑截获PHP读取源文件的接口.一开始,我考虑从Apache和PHP 之间的接口处处理,参见apache的src/modules/php4/mod_php4.c (这个是PHP用static方式编译进apache,make install 后的文件),在send_php()函数中截获文件指针,采用临时文件的方式,解密后替换文件指针.这种方法经过测试实践,证明是可行的.但是,必须使用两次文件操作,效率低下,而且对于DSO方式不可采用. 双缘敬老院 由此,重新考虑截获PHP读取文件并装

随机推荐