2011-04-13 21 views
7

PHP sınıfları hakkında birkaç soru var ama çok işte gidiyorum, ayrı ayrı istenemez:Bazı (gelişmiş) soruları

ben bina ve özünde am CMS var onun benim baseClass, logger, DB ve modülleri sınıfları var. DB ve logger statik sınıflardır, bu yüzden bunları diğer nesnelerden kullanabilirim.

class baseClass { 
    private $_modules; 

    public function __construct() { 
     logger::log("instance created."); 
     $this->_modules = Array() 
    } 

    public function __destruct() { 
     foreach($this->_modules as $name) $this->unloadModule($name); 
     logger::log("instance destroyed."); 
    } 

    public function loadModule($name) { 
     if (class_exists($name)) { 
      if (!isset($this->$name)) { 
       $this->_modules[] = $name; 
       $this->$name = new $name(); 
       logger::log("module '$name' loaded."); 
      } 
      else logger::log("module '$name' already loaded.", 2); 
     } 
     else logger::log("module '$name' does not exist.", 3); 
    } 

    public function unloadModule($name) { 
     if (isset($this->$name)) { 
      unset($this->$name); 
      foreach($this->_modules as $id => $mod_name) { 
       if ($name==$mod_name) { 
        unset($this->_modules[$id]); 
        logger::log("module '$name' unloaded."); 
       } 
      } 
     } 
     else logger::log("module '$name' not loaded.", 2); 
    } 

    public function listModules() { 
     return $this->_modules; 
    } 
} 
$instance = new baseClass(); 
$instance->loadModule('moduleX'); 
$instance->loadModule('moduleY'); 

Soru 1: benim loadmodule uygulaması iyi bir fikir mi yoksa daha iyi bir çözüm var Orada ile AnaSınıf yüklenir modül sınıflarının bir yeri vardır.

:

class moduleX reverseExtends baseClass { 
    public function f1(); 
    public function f2(); 
} 
class moduleY reverseExtends baseClass { 
    public function f3(); 
    public function f4(); 
} 

$instance = new baseClass(); 
$instance->f1(); 
$instance->f2(); 
$instance->f3(); 
$instance->f4(); 

Veya en azından: Ya da tam tersi bir sınıf genişletmek için, bu yüzden modülleri yüklemek için olmazdı, bunun yerine kendi sınıf tanımı gibi AnaSınıf kendilerini yük olacağını mümkündür

$instance->moduleX->f1(); 
$instance->moduleX->f2(); 
$instance->moduleY->f3(); 
$instance->moduleY->f4(); 

Soru 2: şimdi (ben kaydedici :: ve DB ile diyoruz statik sınıflar olarak benim logger ve DB sınıfları kullanıyorum için: :) herhangi bir bağlam ve kapsam erişilebilir, böylece - örneğini mümkündür onları ve onları baseClass nesnesinin içinde kullanmaya devam ediyorum, ancak bunları baseClass'ın içine yerleştirmeden veya bunları bu şekilde ayarlamadan kötüden sarıcı işlevleri kullanmak gibi çirkin AnaSınıf içindeki orijinal nesnenin bir başvuru aktarma gibi değişen

public function __construct() { 
    global $logger_instance; 
    $this->logger = $logger_instance; 
} 

denedim farklı yöntemlerin: Her sınıf içinde ben ile kullanmak için gidiyorum. BaseClass unset olduğu ve modüller üzerinden erişilmesi zor olduğunda, referansları kullanmak benim logger nesnesini yok eder - $ this-> base-> logger-> log() - bu da baseClass nesnesine ($ this-> base) bir başvuru gerektirir ve unloadModule'deki baseClass nesnesini öldürür ... Sarmalayıcı işlevine gelince - logger nesnesinin birden çok örneğine sahip olmak istiyorum, böylece işlevle birlikte bir örnek tanıtıcıyı iletmek onu gerçekten çirkin ve 'yanlış' bir çözüm haline getirir.

public function someFuncionInsideSomeClass() { 
    $logger->('Log something'); //or $logger('Log something') with __invoke() 
    //$logger here is in the global scope 
} 

Soru 3:

gibi bir şey gerekir Bir modül başka birinin kodunu değiştirmek isterler. Örneğin, bir veritabanı modülü yüklü, daha sonra bir logger modülü yüklüyorum ve logger modülünün orijinal kodla uğraşmak zorunda kalmadan veritabanı modülü koduna entegre edilmesini istiyorum. Tabii ki logger entegrasyonun kendisiyle ilgilenmek zorundaydı (ya da kodlayıcı olarak bana göre). Basit bir örnek:

class tagCreator { 
    public function createTag($tag,$data) { 
     $tag1 = $tag; 
     $tag2 = '/'.$tag; 
     return "<$tag1>$data<$tag2>"; 
    } 
} 
class styleFunctionality { 
    public function __construct() { 
     //if class is loaded (tagCreator) | load class (tagCreator) 
      //do some magic here to tagCreator 
      //tagCreator -> createTag -> add argument $style 
      //tagCreator -> createTag -> $tag1 += ' style="'.$style.'"' 
     //else issue error tagCreator does not exist 
    } 
} 
$instance = new baseClass(); 
$instance->loadModule('tagCreator'); 

echo $instance->createTag('span','some string'); 
// returns <span>some string</span> 

$instance->loadModule('styleFunctionality'); 

echo $instance->createTag('span','some string','font-weight: bold'); 
// returns <span style="font-weight: bold">some string</span> 

Not: Ben mutlaka işlevlerin farklı kastetmiyorum, bir yöntem içinde kod sadece biraz değiştirmek isteyebilirsiniz

Not 2: (> createTag instance- $ çağrılması) bir hata değil - ben buraya kadar okuduğunuz için uzun bir konu için

Maalesef yüklü bulunduğu modüllerden yöntemleri ve teşekkür almaya AnaSınıf için çağrı() işlevi __ bazı fantezi yazma planı, Bence hatta appreciat Sorularımdan yalnızca birine bir cevap verin :)

+0

Q1 - Sınıflarınızı talep üzerine yüklemek için otomatik yüklemeyi kullanabilirsiniz, böylece ikinci arama yönteminiz mümkündür: $ örnek-> modYB> f4(); '. S2 - Bence statik yöntem oraya gitmenin yolu olacaktı. – JohnP

+0

Bunu düşündüm, ama bazen tüm modüllerin açıklanabileceğini söyleyebilirim, ama hepsinin baseClass'a yüklenmesini istemem. –

+0

Daha fazla detayla cevap verdim. Temel sınıfınıza yüklenmemelisiniz – JohnP

cevap

3

DB ve Logger için, bir Singleton desen kullanmayı düşünürdüm.

Genel olarak, Kohana gibi PHP5 gerektiren PHP çerçevelerine bakmak isteyebilirsiniz. Ve, kalıplar ve PHP devam ettikçe, "PHP Nesneleri, Kalıpları ve Uygulamalarını" kontrol etmek isteyebilirsiniz.

+0

Sadece hata ayıklama işleviniz olduğu için Logger için Singletone kullanmanızı öneririm ve daha sonra üretimde devre dışı bırakılır ... Veritabanı için Tekton kötü bir tada sahiptir çünkü her zaman sorunlarınız olacaktır. Kodunuzu daha sonra test etme (tercih ederseniz) – chozilla

1

Q1 - Sınıfları yüklemek için autoloader function kullanırdım.Yüklemeye çalıştığınız sınıfın konumunu ve türünü öğrenmek için sınıf adını ayrıştırabilirsiniz (örn. - denetleyici, modül, eklenti vb.).

__get() (temel sınıfınızda) ile birlikte isterseniz, modüllerinizi $instance->moduleX->f1(); gibi arayabilirsiniz.

Q2 - Bu tür etkinlikler için statik sınıfları da kullanıyorum. Global olarak erişilebilir bir değişkene sahip olmanın yanı sıra - diğer alanlarda kodunuzla çelişme riskiyle - yapabileceğiniz başka bir şey yoktur.

Q3 - başarmak için çalışıyoruz ne benzer bir şey için bir kalıp var, ama benim yaşam için şu anda bunu hatırlamak gibi olamaz. Ama nasıl gidiyor, değiştirici sınıfınızı ana sınıfınızla kaydetmeniz gerekecek. Uygulamanızı nasıl yapılandırdığınıza bakarak, temel sınıf modülleri dizisine bakarak veya değiştirici sınıfını ana sınıfınıza geçirerek (tagCreator) bunu yapabilirsiniz.

Ancak, bunu yapmaya karar verdiğinizde, çıktıyı döndürmeden önce yüklenen değiştirici sınıflarını (styleFunctionality) aramak için createTag() yöntemini değiştirmeniz gerekir. Değiştirici sınıflarınız elbette ana sınıfınızın çağırması için bir çeşit standart arayüze ihtiyaç duyacaktır.

Modüllerinizi aynı örnek içine nasıl yüklediğinize bakarak, bir uyarı uyarısı. İki sınıfın aynı yöntemi tanımlaması durumunda çakışmalarınız olabilir. Bunlara $this->ModuleA->aMethod() gibi ayrı olarak erişmenizi öneririz.

+0

Q3 için fabrika modelini mi arıyorsunuz? – preinheimer

+0

@preinheimer nope, fabrika modelini değil. Nesneleri yaratmak için iyi. Google neyin – JohnP

+0

Ohh neyin çok karışık olduğunu görelim. Gözlemci? http://en.wikipedia.org/wiki/Observer_pattern – preinheimer