PHP dinamik bir sınıf Boşaltma

6 Cevap

Aşağıdaki şekilde eklentileri dinamik yükleme uygulanmaktadır:

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

Her eklenti çalışıyor PlginImpl adında bir sınıfı tanımlar. Ama process() dönüş değeri içinde içinde belirtilen başka eklentileri aramak mümkün olmalıdır. Yukarıda belirtilen aynı yöntemi çağırmak, ancak başarısız olur:

Fatal error: Cannot redeclare class PlginImpl in ..

Her eklenti bir sınıf olduğuna dikkat edin, yani:

class PlginImpl extends Plugin implements PluginInterface

Plugin bazı kullanışlı işlevler sunarken PluginInterface tanımlar yani process().

Ben tüm eklentileri PlginImpl adlandırılmış olması dolayısıyla benim soru, soruna neden olduğunu varsayalım: require_once ile yükledikten sonra (PlginImpl) bir sınıf boşaltmak için bir yol var? Ya da ben takip etmelidir tamamen farklı bir yaklaşım var mı?


EDIT I tried without succeeding the following things:

  • unset $plgin sonra, process()
  • bunun içinde processPlugin(), ne process yöntemi içinde de çalışmıyor - __destruct() çağrı

Çok, çok teşekkürler!

6 Cevap

Bunu yükledim sonra bir sınıf kaldıramıyor yana, sahip tek seçenek her eklenti yeniden adlandırmak için.

Eğer sadece gösterdi eklenti arabirimi kullanmak için zorlayabilir vb gibi PluginX, PluginY, ama bu önemli değil.

Belirli bir eklenti yüklemek için solomongaby anlaşılacağı gibi, sadece bir şey olabilir, ancak bunun yerine bir dosya adı, sen .. bunu böyle bir şey Eklentinin adı geçmesi:

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

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

Başka bir seçenek, ben bunu tavsiye etmiyoruz ama, kullanmak için runkit_import.

Ben% 100 emin değilim, ama ilan etti kez bir sınıf kaldıramıyor inanmıyorum.

Ancak, is yapmak için çalışıyoruz ne başarmak için bir yol.

Farklı her sınıf isim ve sonraki oluşturmadan önce tek bir sınıf yok:

$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;
}

Sen etrafında asılı fazladan tanımlı sınıfları olacak, ama bir kez yüklü eklenti unsetting umarım bellek sorunları en aza indirmek gerekir.

Ben soru yıllar önce yayınlanmıştır olmuştur biliyorum, ama ben bugün bu konuya çöktü ettik, ben bu günlük nasıl gideceksin gelecekte de aynı sorun var yardımcı olabilir umuyoruz.

It'has birçok cevaplarında belirtildiği gibi, PHP (en az 5.3 kadar) sınıfları boşaltmaya izin vermez; ne tek yapabileceğiniz isimleri arasındaki çatışmaları önlemek için. Ben eşsiz bir ad, her eklenti yük bir kod yazdık göz önünde tutarak bu.

$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);

Eklenti yazarlar başvurulan sınıflar konak onun için yarattığı bağlamına ilişkin içindir farkında olmalıdır.

Sen plgun-> süreci () yöntemini çağırır Deconstructor sahip bakmak olabilir http://ca.php.net/manual/en/language.oop5.decon.php

Veya

Sen $ plgin-> sürecinin sonucu olabilir () geçici var saklanan ve daha sonra unset ($ plgin)

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

Ancak muhtemelen sert bir şekilde sorunu yaklaşan düşünüyorum.

Belki bir sınıf Plugin olmalı ve daha sonra () bir yöntem olarak uygulanması var.

Ben bir sınıf eklenti yükleme işlemek için yapacak

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;
  }
}

ve kullanmak için öncelikle bir yapardın

pluginLoader::instance($db);

ve daha sonra bir eklenti yüklemek için

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