Разгрузите динамический класс в PHP

Я реализовал динамическую загрузку плагинов следующим образом:

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_once? Или есть ли совершенно другой подход, за которым я должен следовать?


ОТРЕДАКТИРУЙТЕ я попробовал, не следуя за следующими вещами:
  • сброс $plgin после process()
  • вызов __destruct() - это не работает ни один в processPlugin() ни в process метод
7
задан Benjamin 28 June 2019 в 16:39
поделиться

5 ответов

Поскольку вы не можете выгрузить класс после его загрузки, единственный вариант, который у вас есть, - это переименовать каждый плагин.

PluginX, PluginY и т. Д., Но это не должно ' Это имеет значение, поскольку вы можете просто заставить их использовать интерфейс плагина, как вы показали.

Чтобы загрузить конкретный плагин, вы можете просто предложить что-то вроде solomongaby, но вместо имени файла вы передадите ему имя плагина. . Примерно так:

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

    $plugin = new $pluginName;
    //do whatever with $plugin
}
11
ответ дан 6 December 2019 в 11:51
поделиться

Другой вариант, хотя я не рекомендую его, - это используйте runkit_import .

4
ответ дан 6 December 2019 в 11:51
поделиться

Я не уверен на 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;
}

У вас будет несколько дополнительных определенных классов, но отключение плагина после его загрузки должно минимизировать проблемы с памятью.

1
ответ дан 6 December 2019 в 11:51
поделиться

Вы можете посмотреть, как метод plgun-> process () вызывает деконструктор http://ca.php.net/manual/en/language.oop5.decon.php

Или

Вы можете сохранить результат $ plgin-> process () во временной переменной, а затем отключить его ($ plgin)

function processPlugin( $plgFile, $db ) {
  require_once( $plgFile );
  $plgin = new PlginImpl();
  $plgin->setDb($db);
  $result = $plgin->process();
  unset($plgin);
  return $result;
}

Однако я думаю, что вы, вероятно, решаете проблему с трудом.

Вам, возможно, следует иметь подключаемый модуль класса, а затем иметь метод Implement ().

0
ответ дан 6 December 2019 в 11:51
поделиться

Я бы создал класс для обработки загрузки плагина

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);  
0
ответ дан 6 December 2019 в 11:51
поделиться