Objekt einer Klasse in anderer Klasse nutzen
Markus
- php
Hallo,
ich habe eine Datenbanklasse die den kompletten Zugrif auf eine Datenbank regelt. Es gibt immer nur ein Objekt der Datenbankklasse. Im moment Arbeite ich an einer Klasse um Session zu verwalten und dabei werden Daten aus der Datenbank benötig bzw etwas in die Datenbank geschrieben. Dazu möchte ich auch das Objekt der Datenbankklasse verwenden. ICh möchte keine Globalen Variablen nutzen und würde sie ungern an das Objekt der Datenbankklasse an die Sessionklasse übergeben. Leider habe ich immernoch keine lösung dafür. Kann mir jemand weiterhelfen?
Gruß
Markus
你好 Markus,
Dazu möchte ich auch das Objekt der Datenbankklasse verwenden. ICh möchte
keine Globalen Variablen nutzen und würde sie ungern an das Objekt der
Datenbankklasse an die Sessionklasse übergeben. Leider habe ich immernoch
keine lösung dafür. Kann mir jemand weiterhelfen?
Für solche Probleme gibt es das Design-Pattern „Singleton“. Das sorgt
dafür, dass nur eine Instanz einer Klasse existieren kann. Dazu musst du
allerdings bei PHP Disziplin aufbringen, du darfst dann nämlich den
Konstruktor nicht mehr direkt benutzen! Ich gebe dir mal eine
Beispiel-Implementation:
class singleton {
function sigleton($host,$user,$pass,$db) {
# mach was, Verbindung herstellen, etc, pp
}
function getInstance($host,$user,$pass,$db) {
static $instance;
if(!isset($instance)) $instance = new sigleton($host,$user,$pass,$db);
return $instance;
}
}
Jetzt kannst du an jeder Stelle deines Codes die gleiche Instanz deiner
Datenbank-Klasse bekommen, indem du getInstance() aufrufst:
$db =& singleton::getInstance("param1","param2","param3","param4");
再见,
克里斯蒂安
Hallo,
ich habe schon mehr bei der Problemlösung das wort Singleton gefunden. Allerdings nie verstanden weil die Beispiele einfach zu groß waren. In dieser einfachen Form ist mir nun Klar wie das Funktioniert (nachdem ich static nochmal nachgeschlagen habe). Danke, hat mir wirklich sehr geholfen.
Gruß
Markus
echo $begrüßung;
Gestattest du eine Korrektur und zwei Anmerkungen? (-:
> class singleton {
> function sigleton($host,$user,$pass,$db) {
> # mach was, Verbindung herstellen, etc, pp
> }
>
> function getInstance($host,$user,$pass,$db) {
Bei Rückgabe einer Referenz muss das & sowohl bei der Funktionsdeklaration als auch bei der Verwendung angegeben werden:
function &getInstance($host,$user,$pass,$db) {
> static $instance;
>
> if(!isset($instance)) $instance = new sigleton($host,$user,$pass,$db);
Hier kann es sinnvoll sein, eine Referenz des erzeugten Objekts statt einer Kopie davon zu speichern. Das kommt hauptsächlich drauf an, ob mit weiteren Referenzen im Konstruktor gearbeitet wird.
if(!isset($instance)) $instance =& new sigleton($host,$user,$pass,$db);
return $instance;
}
}
>
> Jetzt kannst du an jeder Stelle deines Codes die gleiche Instanz deiner
> Datenbank-Klasse bekommen, indem du getInstance() aufrufst:
>
> ~~~php
> $db =& singleton::getInstance("param1","param2","param3","param4");
>
Abschließend sei noch darauf hingewiesen, dass PHP5 bei der Übergabe von Objekten von Haus aus mit Referenzen statt Kopien arbeitet, die & also entfallen können.
Wenn man nicht kompatibel zu PHP4 sein muss/möchte hält das Handbuch eine Implementation des Singleton-Patterns bereit: http://de2.php.net/manual/en/language.oop5.patterns.php
echo "$verabschiedung $name";
hallo,
Hier kann es sinnvoll sein, eine Referenz des erzeugten Objekts statt »» einer Kopie davon zu speichern. Das kommt hauptsächlich drauf an, ob »» mit weiteren Referenzen im Konstruktor gearbeitet wird.
in diesen Part verstehe ich noch nicht ganz warum es sinnvoll sein kann eine Referenz eines Objektes statt einer Kopie zu speichern, in den Konstrukter der Datenbankklasse stelle ich die Verbindung zur DB her. Es werden keine Referenzen benutzt.
Gruß
Markus
你好 markus,
Hier kann es sinnvoll sein, eine Referenz des erzeugten Objekts
statt einer Kopie davon zu speichern. Das kommt hauptsächlich drauf
an, ob mit weiteren Referenzen im Konstruktor gearbeitet wird.in diesen Part verstehe ich noch nicht ganz warum es sinnvoll sein kann
eine Referenz eines Objektes statt einer Kopie zu speichern, in den
Konstrukter der Datenbankklasse stelle ich die Verbindung zur DB her. Es
werden keine Referenzen benutzt.
Weil du die Kopie nicht benötigst.
Das kopieren eines Objektes kostet Zeit und braucht Ressourcen. Je größer
das Objekt, desto schlimmer wird es. Darum sollte man die Kopie vermeiden,
wenn möglich.
再见,
克里斯蒂安
echo $begrüßung;
Hier kann es sinnvoll sein, eine Referenz des erzeugten Objekts statt einer Kopie davon zu speichern. Das kommt hauptsächlich drauf an, ob mit weiteren Referenzen im Konstruktor gearbeitet wird.
in diesen Part verstehe ich noch nicht ganz warum es sinnvoll sein kann eine Referenz eines Objektes statt einer Kopie zu speichern, in den Konstrukter der Datenbankklasse stelle ich die Verbindung zur DB her. Es werden keine Referenzen benutzt.
Einen Grund hat Christian schon genannt. Der ist jedoch unter PHP nur bei großen Datenstrukturen relevant. Siehe dazu den eingerückten Abschnitt "Note: There is no performance loss ..." im Handbuchkapitel References inside the constructor.
Ansonsten beschäftigt sich die verlinkte Handbuchseite mit dem Hauptgrund, mit einer Referenz auf das erzeugte Objekt statt einer kopie zu arbeiten. Zugegeben, dieser Stoff ist recht schwer zu verstehen, vielleicht ist folgendes Beispiel einfacher:
class ElementsCollection {
function &getElements() {
static $elements = array();
return $elements;
}
function addElement($id, &$element) {
$elements =& ElementsCollection::getElements();
$elements[$id] =& $element; // *3
}
}
class Element {
var $id;
var $content = 'Default-Wert';
var $children = array();
function Element($id) { // Element-Constructor
$this->id = $id;
ElementsCollection::addElement($id, $this); // *2
}
function &addChild($id) {
return $this->children[$id] = new Element($id); // *5
// return $this->children[$id] =& new Element($id); // *8
}
}
$parent =& new Element('foo'); // *1
$child =& $parent->addChild('bar'); // *4
$child->content = 'neuer Wert'; // *6
echo '<pre>';
print_r(ElementsCollection::getElements());
Ausgabe:
Array (
[foo] => element Object (
[id] => foo
[content] => Default-Wert
[children] => Array (
[bar] => element Object (
[id] => bar
[content] => neuer Wert
[children] => Array ()
)
)
)
[bar] => element Object (
[id] => bar
[content] => Default-Wert // *7
[children] => Array ()
)
*1 Es wird ein $parent-Objekt der Klasse Element mit der ID 'foo' erstellt.
*2 Das Element fügt sich im Constructor selbst in die ElementsCollection ein.
(Die ElementsCollection ist eine Klasse, deren Methoden nur statisch aufgerufen werden. Es existiert kein Objekt dieser Klasse. Dadurch wird sichergestellt, dass es die Kollektion der Elemente nur einmal gibt. Aufgabe der ElementsCollection ist, auf alle Elemente direkt zugreifen zu können, egal wie tief die Verschachtelung geht.)
*3 Die ElementsCollection speichert eine Referenz auf das 'foo'-Objekt.
*4 Nun wird ein neues Kind-Element mit der ID 'bar' zu $parent hinzugefügt.
*5 Durch Aufruf des Konstruktors (new Element) wird das neu erzeugte 'bar'-Element zur ElementsCollection hinzugefügt. Allerdings wird nur eine Kopie des 'bar'-Elements im children-Array von 'foo' abgelegt.
Außerdem soll addChild() auch eine Referenz auf das eben erstellte Element zurückgeben. (Momentan liefert es nur eine Referenz auf eine Kopie zurück.)
*6 Der Wert von content des 'bar'-childs soll geändert werden.
*7 Da hier allerdings nur noch eine Kopie auf das eigentlich unter *5 mit new angelegte Element vorliegt, wird der direkte Eintrag von 'bar' in der ElementsCollection nicht geändert.
*8 Wird diese Zeile statt der *5 verwendet, bleibt die Beziehung zwischen $child und dem 'bar' in der ElementsCollection erhalten.
echo "$verabschiedung $name";
P.S. Da dieses Beispiel eine Konzeptionsschwäche enthält, die beim Versuch einzelne Elemente zu löschen auffällt, ist es mehr zur Veranschaulichung der Referenzproblematik und als zu einem praktischen Einsatz geeignet.
Hallo,
nochmal Danke für die umfangreiche Erklärung. Ich hab die Problematik verstanden. Im moment hoffe ich das ich auf solche Probleme noch nicht stoßen werden. Aber es ist gut zu wissen wie man es dann richtig macht.
Danke für eure Hilfe
Markus