2016-03-22 25 views
0

Şu anda bir otomatik ayarlayıcı üzerinde çalışıyorum ve tüm iyi çalışıyor ve çalışıyor, ancak üzerlerinde bazı ciddi kısıtlamalar var. Ben rastladımSırasıyla sürekli bağımlılık yüklemesi

biri konudur aşağıdadır:

Şimdi
trait constructor{} 
trait cache{} 
trait database{} 
trait settings{} # requires database or cache. 

benim otomatik yükleme sistemi ben şöyle doğru sırayla kullanımını tanımlamak gerekir çalışması için:

class t{ 
    use constructor, cache, settings; 
} 

isterim Eğer aşağıdakileri yapın:

class t{ 
    use constructor, settings, cache; 
} 

Ayarlar trait başlatıcısı, önbellek ilk önce çağrılır. izer ve böylece önbellek özelliğinin içindeki $cache değişken boştur.

Şimdi, ayar özelliğine use cache, database; eklemek basit bir çözüm olacaktır, ancak bu, dahil edilmesi gereken başka bir özellik tarafından kullanılıyorsa tanımlı yöntemlerin çakışmasına neden olabilir. Başka bir çözüm, $cache numaralı özelliğin tanımlanmış olup olmadığını kontrol etmek ve ardından ayarlanıp ayarlanmadığını kontrol etmek olacaktır, ancak bu, her bir özellik için yazmak istemediğim çok fazla yedek kod oluşturacaktır.

trait constructor{ 
    function init(){ 
    echo 'I am called first'; 
    print_r(class_uses(self::class))/*[ 
     'constructor' => 'constructor', 
     'cache' => 'cache', 
     'database' => 'database', 
     'settings' => 'settings' 

     // Sorted in sequence as defined in the class. 
    ]*/ 

    # now call other trait initializers. 
    } 
} 

trait settings{ 
    function settings(){ 
    echo 'I am called last, but before __construct()'; 
    } 
} 

class t{ 
    use constructor; // required by all traits 
    use cache;  // requires constructor. 
    use database; // requires constructor. 
    use settings; // requires constructor, cache || database. 

    function __construct(){ 
    echo 'I am called after init()'; 
    $this->db->prepare(...)->execute(); 
    } 
} 

Emin ayarlarını yapmak için diziyi sıralamak mümkün yapıcı olduğu önbelleği veya veritabanı sonra dizine:

Şimdi kod mantığı şudur. Ancak burada zor kısmı geliyor, en iyi yaklaşım bunun için nedir?

Çoğu sınıf yalnızca az sayıda özellik kullandığı için, sıralama için temel olarak kullanılacak uzun bir diziyi tanımlamak yetersiz görünür. Bu sistem CMS'nin merkezinde çalıştığı için, özelliğe göre bir özelliği sıralamak istiyorum.

Özelliklerle ilgili sorun, aynı şeyi sınıfta iki kez tanımlayamamam ve aynı zamanda kapsam kirliliğini en aza indirmek istiyorum.

+0

İlginç. Bağımlılık sorunları (ve/veya bunları yükleyen istemci sınıfları) ile bağımlılık sorunları yaşıyoruz ve kullanımlarından kaçınmaya karar verdik ve bağımlılık enjekte edebileceğimiz uygun sınıfları kullanıyoruz. Bununla birlikte, bazı durumlarda bu, iyi bir çözümden ziyade daha az kötülüktür. Sadece merak, hangi PHP sürümünü hedefliyorsunuz? Ben soruyorum çünkü 5.4 ile 5.6 arasında ve belki de 5 ile 7 arasında değişiyor. –

+0

Şu anda özellikle PHP 7 için yeniden yazıyordum, ancak bu büyüyü gerçekleştirmek için kullanılan kod 5.4 ile çok uyumlu. – Xorifelse

cevap

0

Çok fazla kod gerektirmeden sorun için geçerli bir çözüm buldum.

trait constructor{ 
    private $traits; 

    function loaded(array $list){ 
    foreach($list as $trait){ 
     if(isset($this->_traits[$trait])){ // class_uses returns array of ['trait' => 'trait'] while I append numeric. 
     $this->_traits[] = $this->_current; // append the current looping method (of init) to be loaded last. 
     return false; 
     } 
    } 
    return true; 
    } 

    function init(){ 
    $traits = class_uses(self::class); 
    while(list(,$method) = each($this->traits)){ 
     unset($this->_traits[$method]); // avoid infinite loop. 
     // This while loop will loop trough newly added values added by 'loaded' 
     call_user_func([$this, $method]); 
    } 
    } 
} 

trait settings{ 
    function settings(){ 
    if($this->loaded(['cache', 'database'])){ 
     # This method will queue the 'settings' method for later regardless if the traits are already loaded. 
     # So it will first load the traits that don't have dependency's. 
     # The order is not important because the __construct method is called last anyways. 
    } 
    } 
} 

Başka herhangi bir öneri varsa, yalnızca bir yanıt ekleyin.