tiptop, funktioniert :-)
Damit ist mein jit-Entwurfsmuster fertig.
Die benötigten Instanzen werden jetzt Just in Time erzeugt *froi*.
Für alle die es interessiert:
Ich programmiere an einem größeren Shop-System (seit etwa 4 Jahren, vor 1,5 Jahren haben wir alles auf PHP5 im OOP-Style umprogrammiert).
Um global benötigte Objekte einfach anzusprechen, haben wir über statische Klassen ohne Instanz "Pseudo-Namespaces" erzeugt über die dann via "__autoload()" überall zugegriffen werden kann.
Mein Problem war die Datenbankzugriffsklasse, die an unzählbaren Stellen verwendet wird, und von der eine Instanz existieren muss ( DB-Verbindung). Allerdings gibt es auch viele Seiten mit hohem Traffic, die aufgrund des Cachings keinen Datenbankabfragen benötigen. Da die Seiten in "kleinen Happen" gecacht werden kann aufgrund der dynamisch erzeugten Inhalte vorher nicht ohne viel Rechenaufwand bestimmt werden ob ein DB-Zugriff notwendig wird.
Aus Performacegründen sollte aber pro Seitenaufbau maximal eine DB-Connection existieren, über die dann alle Objekte ihre Abfragen machen. Eine Singelton-Klasse schied aber auch wieder aus, da es unter Umständen mehrer DB-Klassen gibt, die jeweils auf unterschiedliche Datenbanken zugreifen.
Um dennoch überall ganz einfach (zB. "c::$db->query($sql)" Abfragen gegen die DB zu starten, ohne überprüfen zu müssten, ob die Datenbankverbindung schon existiert haben wir hier eine Lösung geschaffen.
Ich freue mich auf eure Meinung dazu!
PHP-Code:
// "Namespace" imitieren, damit oft benötigte Klassen global erreichbar sind
class dummyclass {
private $vname; // Name der Variable
private $cname; // Name der Klasse
//##########################################################################
public function __construct ($vname, $cname) {
$this->vname = $vname;
$this->cname = $cname;
}
//##########################################################################
public function __get($prop) {
c::createclass($this->vname, $this->cname);
return c::execute($this->vname, 'get', $prop);
}
public function __set($prop, $value) {
c::createclass($this->vname, $this->cname);
return c::execute($this->vname, 'set', $prop,$value);
}
public function __call($method, $args) {
c::createclass($this->vname, $this->cname);
return c::execute($this->vname, 'call',$method, $args);
}
//##########################################################################
}
class c {
static public $db;
static public $tpl;
static private $classes;
//##########################################################################
static public function setup() {
self::$db = new dummyclass('db', 'cmysqldbi');
self::$tpl = new dummyclass('tpl','ctpl');
self::$classes = array();
}
//##########################################################################
static public function execute($vname,$action, $arg1, $arg2 = NULL) {
switch ($action) {
case 'get':
$retval = c::$classes[$vname]->$arg1;
break;
case 'set':
c::$classes[$vname]->$arg1 = $arg2;
$retval = true;
break;
case 'call':
if (!is_array($arg2))
$arg2 = array();
$retval = call_user_func_array (array(self::$classes[$vname],$arg1),$arg2);
break;
}
return $retval;
}
//##########################################################################
static public function createclass ($vname, $cname) {
if (!is_a(self::$classes[$vname], $cname))
self::$classes[$vname] = new $cname;
}
//##########################################################################
}
der Quelltext ist Zwecks der Übersicht stark vereinfacht, die Fehlerbehandlung (Überprüfen, ob die entsprechenden Funktionen existieren, public sind etc.) wurde weggelassen