在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()
方法中工作进程
您可能应该有一个类插件,然后让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);