Moin!
Meine Lösung, wie ich (glaube ich) schon mal gepostet habe:
Config.cfg.php
class Config { $farbe = 'rot'; function getAttribut() { return $this->farbe; } }
Auto.class.php
class Auto { $farbe; function __construct( $farbe ) { $this->farbe = $farbe; } }
index.php
include( 'Config.cfg.php' ); include( 'Auto.class.php' ); $cfg = new Config(); $auto = new Auto( $cfg->farbe );
Das ist Dependency Injection, und genau so sollte man es machen.
Was man nicht machen sollte:
- Keine globalen Variablen, keine globalen Konstanten (Klassenkonstanten lassen sich ja zum Glück nicht dynamisch definieren, außer man schreibt dynamischen Code und ruft
eval()
auf - igittiwürg), keine global existierenden Konfigurationsobjekte, die in die Klassen getan werden. Insbesondere kein Config-Singleton. Alle diese Varianten bedeuten, dass der Konsument der Konfigurationswerte wissen muss, wie dieser Wert heißt, bzw. wo dieser gefunden werden kann. Es bedeuten gleichzeitig, dass bei Wiederverwendung des Codes der Wert im neuen Projekt an die gleiche Stelle getan werden muss. - Keine Setter für Konfigurationswerte. Einen Setter muss man nicht zwingend aufrufen, zumindest nach der Codelogik nicht, man kann ihn aufrufen. Vor allem kann man ihn mehrfach aufrufen. Im Setter und im Nutzcode der Klasse müsste deshalb erstens Code sein, der meckert, wenn der Setter noch nicht aufgerufen wurde, der Wert aber gebraucht wird. Zweitens verhindert, dass ein zweiter Aufruf erfolgen kann. Diese beiden Probleme verschwinden sofort, wenn man den Parameter als Argument im Konstruktor platziert. Der Konstruktor kann nur einmal pro Instanz aufgerufen werden, und sofern kein Default-Wert angegeben ist, ist auch klar ersichtlich: Diese Klasse braucht ZWINGEND diese Parameter.
- Ein wichtiges Argument gegen Setter (mindestens für Konfiguration) ist: Konfiguration ist "state". Eine Klasse kann als identische Instanz an mehreren Stellen referenziert werden, und mit Settern würde die Möglichkeit bestehen, diesen Zustand der gemeinsamen Instanz zu ändern, ohne dass man das mitkriegt. Nur mal kurz nachdenken: Eine DB-Instanz bekommt Servernamen und Zugangsdaten per Setter übergeben und wird als dieselbe Instanz in zwei Klassen verwendet. Eine Klasse setzt initial ihren Test-Server und dessen Zugangsdaten, die andere erwartet eine fertig konfigurierte DB-Instanz. Solange die vorkonfigurierte DB-Instanz auch den Testserver benutzt, ist alles prima. Und dann wird auf den Produktivbetrieb umgestellt, und Produktivdaten gehen auf dem Testserver verloren, bzw. Testdaten werden in Produktion sichtbar... Und die Entwickler können in der Testumgebung nichts verdächtiges finden.
Grüße Sven