2011-01-05 3 views
2

Ich benutze eine Factory-Klasse, um die Instanziierung von Objekten zu verwalten und in ihre Konstruktoren alle Abhängigkeitsobjekte (Dependency Injection) z.PHP OOP :: Halte Config 'globale' Werte für alle Klassen zugänglich

function createBasket() { 
    //pass in dependent objects 
    $apiCon = $this->createAPIConnector($this); 
    $basket = new Basket($this, $apiCon); 
    return $basket; 
} 

Ich versuche, das ‚neue‘ Schlüsselwort in allen Klassen (außer Factory) zu vermeiden, mit, einfachen und robusten Unit-Test zu ermöglichen, klaren Code usw.

Nun bezieht ich meine Frage Konfigurationswerte, die viele Klassen benötigen, z

$apiURL = 'http://some.api.com'; 
$apiKey = 'abcde12345'; 
$adminEmail = '[email protected]'; 

Diese Werte bleiben für jede Anwendungsinstanz konstant. Ich habe sie zur Zeit in einer Singletonklasse Config und sie sind erreichbar aus jeder Klasse durch die folgenden:

$cfg = Config::getInstance(); 
$address = $cfg->apiURL; 

jedoch diese Klasse Instanz ist immer noch eine Abhängigkeit innerhalb einer Klasse, die es nennt, also soll ich darüber nachdenken, beiläufig dies in Klassenkonstruktoren, z

function createBasket() { 
    //pass in dependent objects 
    $apiCon = $this->createAPIConnector($this); 
    $cfg = Config::getInstance(); 
    //pass singleton config object to constructor 
    $basket = new Basket($this, $apiCon, $cfg); 
    return $basket; 
} 

... oder vielleicht sie über eine Set-Methode, anstatt über Konstruktor in:

function createBasket() { 
    //pass in dependent objects 
    $apiCon = $this->createAPIConnector($this); 
    $basket = new Basket($this, $apiCon); 
    //pass singleton config object to setter 
    $basket.setConfig(Config::getInstance()); 
    return $basket; 
} 

Alle Leitlinien für den besten Ansatz wäre sehr geschätzt.

Danke, James

+1

* (verwandt) * [Symfony Komponenten Dependency Injection Container] (http://components.symfony-project.org/dependency-injection) – Gordon

+0

Dependency Injection ist der Weg zu gehen – DrDol

Antwort

1

Scheint so, als würde der Zweck eines Singleton-Config-Objekts, das global verfügbar ist, zunichte gemacht. Der ganze Punkt ist, es als Parameter für jede Klasse, die Sie machen, zu übergeben.

+0

Ich versuche sicherzustellen, dass jede Klasse Einheit getestet werden kann. Ich würde wahrscheinlich eher die Singleton-Klasse entfernen, da sie wirklich nur als globaler Halter für Vars agiert. Um die Abhängigkeitsinjektion in meiner App zu erhalten, muss ich sicherstellen, dass diese "globalen" Variablen (und Hilfsfunktionen) an die Klassen weitergegeben werden, die sie benötigen. Es ist verlockend, sie einfach im globalen Raum zu belassen, aber ich bin mir ziemlich sicher, dass ich in 6 Monaten bereuen werde, weltweit so viele Sachen zu haben, was die Unit-Tests schwieriger macht. –

+0

Antwort gegeben. Ich werde den Code so umgestalten, dass er nicht mehr auf ein Singleton angewiesen ist, und die Vars einfach "nach Bedarf" in Konstruktoren einbringen. Erleichtert das Testen von Einheiten und erleichtert das Folgen von Code. –

1

Ive immer gesehen, dass sie als Konstanten gemacht. Ich weiß nicht, dass dies die "beste" Lösung ist, aber ich habe das gesehen und oft benutzt. Da es ein const ist (das gleiche gilt für statische vars, würde ich daran interessiert zu hören, warum man besser ist als der andere), müssen Sie nicht die Klasse instanziieren, die wahrscheinlich Sie einige Overhead sparen würde, wenn Sie pingelig sein wollen ...

class SomeClass 
{ 
    const MYCONS = "APIKEY or Whateva"; 
} 

dann in, wenn Sie verwenden müssen, um die Datei benötigen und etwas zu tun, wie

SomeClass::MYCONST //to get your config info 
+0

Ich benutze eine ähnliche Methode, aber mit Schnittstellen statt Klassen ähnlich Android ContactsContract (http://developer.android.com/reference/android/provider/ContactsContract.html) – Don

+0

Vielen Dank. Ich glaube, meine Sorge hat mehr damit zu tun, dass ich in meinen Klassen keine "versteckte" Abhängigkeit habe. Die Idee, diese Werte explizit in den Konstruktor zu übertragen, macht Code IMO viel klarer, besonders für neue Leute, die an der App arbeiten. Alles, was ein Objekt von uns abhängig macht, wird in den Konstruktorargumenten kristallklar sichtbar. Vielleicht mache ich mir unnötigerweise Sorgen über diese einfachen globalen Variablen, da sie wirklich nur einfache Konfigurationsparameter sind. Es gibt keine Objekte oder große/komplexe Datenstrukturen. Eine Klasse zu erstellen, nur um dieses Zeug zu halten, wird vom OOP-Design nicht profitieren ...hmmm –

0

ich ein ähnliches Verfahren zu verwenden, alles bis in einem einzigen Array oder eine Datei einstellen und ihn zu definieren entsprechend:

$config = array(
    'MYCONST_1'=>'myValue', 
    'USER'=>'username', 
    'PASSWORD'=>'y3ahr1ght' 
); 

foreach($config as $const=>$value){ 
    define($const,$value); 
} 
+0

Wenn ich darf, werde ich Ihrem Codebeispiel höflich widersprechen. Die Verwendung anwendungsweiter Konstanten für Variablen, die zur Laufzeit unterschiedliche Werte haben können, erschwert das Testen. Wenn Sie eine Testsuite pro Klasse in einer einzelnen Testklasse haben, können Sie die Konstante in der Suite nicht ändern 2 Testsuiten für die Datei. Mit anderen Worten: Wenn ich etwas nicht verpasse, wenn Ihre Konstanten hier und da anwendungsweit verwendet werden und mehrere Werte zur Laufzeit im globalen Umfang haben können, fühlt es sich in meiner (bescheidenen) Meinung nicht richtig an. – stefgosselin