Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/256.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在PHP中卸载动态类_Php - Fatal编程技术网

在PHP中卸载动态类

在PHP中卸载动态类,php,Php,我通过以下方式实现了插件的动态加载: function processPlugin( $plgFile, $db ) { require_once( $plgFile ); $plgin = new PlginImpl(); $plgin->setDb($db); $ret = $plgin->process(); return $ret; } 每个插件都定义了一个名为PlginImpl的类,该类工作正常。但是应该可以调用process()的返回值中指定的其他插

我通过以下方式实现了插件的动态加载:

function processPlugin( $plgFile, $db ) {
  require_once( $plgFile );
  $plgin = new PlginImpl();
  $plgin->setDb($db);
  $ret = $plgin->process();
  return $ret;
}
每个插件都定义了一个名为
PlginImpl
的类,该类工作正常。但是应该可以调用
process()
的返回值中指定的其他插件。这将调用上面指定的相同方法,但在以下情况下失败:

Fatal error: Cannot redeclare class PlginImpl in ..
请注意,每个插件都是一个类,即:

class PlginImpl extends Plugin implements PluginInterface
Plugin
提供了一些有用的功能,而
PluginInterface
定义了
process()

我假设所有插件都被命名为PlginImpl这一事实导致了这个问题,因此我的问题是:在加载类(
PlginImpl
)之后,是否有一种方法可以卸载一个类(
require\u一次
?还是有一个完全不同的方法我应该遵循


编辑 我尝试了以下几件事,但没有成功:

  • process()之后取消设置
    $plgin
  • 调用
    \uuu destruct()
    -它既不在
    processPlugin()
    中工作,也不在
    进程
    方法中工作

您可以考虑让plgun->process()方法调用解构器

您可以将$plgin->process()的结果存储在临时变量中,然后取消设置($plgin)

然而,我认为你可能正在以一种艰难的方式处理这个问题


您可能应该有一个类插件,然后让Implement()成为一个方法。

我将创建一个类来处理插件加载

class pluginLoader {
  protected $_plugins = array();
  protected $_db;

  public function setDB($db) {
     $this->_db = $db;
  }


  public function load($plgFile) {
    if (!isset($this->_plugins[$plgFile])) {
      require_once( $plgFile );
      $plgin = new $plgFile();
      $plgin->setDb($this->_db);
      $this->_plugins[$plgFile] = $plgin;
    }
    $this->_plugins[$plgFile]->process();
  }

  public static function instance($db) {
    static $instance;

    if (!$instance instanceof self) {
        $instance = new self($db);
    }
    return $instance;
  }
}
要使用它,你首先要做一个

pluginLoader::instance($db);
然后加载一个插件

pluginLoader::instance()->load($plgFile);  

由于在加载类之后无法卸载它,因此唯一的选择就是重命名每个插件

PluginX、PluginY等等,但这并不重要,因为你可以强迫他们使用你展示的插件接口

要加载一个特定的插件,您可以简单地使用solomongaby建议的东西,但是您可以传递插件的名称,而不是文件名。。大概是这样的:

function loadPlugin($pluginName) {
    require_once $pluginName . '.php';

    $plugin = new $pluginName;
    //do whatever with $plugin
}

我不是100%确定,但我不相信一旦类被声明,就可以卸载它

然而,有一种方法可以完成你想要做的事情

为每个类命名不同,并在创建下一个类之前销毁一个类:

$class1 = "foo";
$class2 = "bar";

$pluginResult = processPlugin($class1);
// do stuff
$pluginResult = processPlugin($class2);

function processPlugin($pluginName, $db) {
    require_once( $pluginName . ".inc" ); //or whatever scheme you want to use.
    $plgin = new $plugin;
    $plgin->setDb($db);
    $ret = $plgin->process();
    unset($plgin);
    return $ret;
}

你会有一些额外定义的类挂起,但是一旦加载了插件就取消插件应该有望减少内存问题。

另一个选项,尽管我不推荐,是使用。

我知道这个问题多年前就已经提出了,但我今天已经崩溃到这个问题上了,我希望这个日志能够帮助我们在将来遇到同样的问题

正如许多回复中提到的,PHP(至少在5.3之前)不允许卸载类;我们能做的就是避免名字之间的冲突。记住这一点,我编写了一段代码,将每个插件加载到一个唯一的名称空间中

$uniqueContext = 'Context_'.rand();
$content = file_get_contents($actionScript);
if (strstr($content, '<?php')) {
    $content = str_replace('<?php', "<?php namespace $uniqueContext;", $content);
} else {
    if (strstr($content, '<?')) {
        $content = str_replace('<?', "<?php namespace $uniqueContext;", $content);
    } else {
        $content = "namespace $uniqueContext;".$content;
    }
}
$tmp=array_search('uri', @array_flip(stream_get_meta_data($GLOBALS[mt_rand()]=tmpfile())));
file_put_contents($tmp, $content);
require_once($tmp);
$uniqueContext='Context'.rand();
$content=file\u get\u contents($actionScript);

if(strstr($content,),我试着如上所述使用unset,但它只卸载PlginImpl的实例,但定义仍保留在内存中(第二次运行失败)。解构器也不起作用。非常感谢-但我不会因为所有插件都被称为“PlginImpl”而遇到与以前完全相同的问题吗?将其与上述解决方案相结合,并使用类文件的插件名称。我不知道这一点。酷:)PHP直到5.3才允许卸载类。那么如何在PHP 5.3+中卸载呢?
$uniqueContext = 'Context_'.rand();
$content = file_get_contents($actionScript);
if (strstr($content, '<?php')) {
    $content = str_replace('<?php', "<?php namespace $uniqueContext;", $content);
} else {
    if (strstr($content, '<?')) {
        $content = str_replace('<?', "<?php namespace $uniqueContext;", $content);
    } else {
        $content = "namespace $uniqueContext;".$content;
    }
}
$tmp=array_search('uri', @array_flip(stream_get_meta_data($GLOBALS[mt_rand()]=tmpfile())));
file_put_contents($tmp, $content);
require_once($tmp);