Willkommen in der Webstatt Zum Webstatt Blog und Stories
Dustwolf Dustwolf am 17.04.06 18:28

Und schon wieder habe ich eine Verständnisfrage. Ich schreibe mir gerade eine Template-Class und dazu brauche ich den Selbstaufruf der Class.

Ich will also innerhalb einer Class eine Variable haben, in der ich die class als neues Objekt ablege. Meine Ahnungslosigkeit auf Grund von sehr seltsamen Tutorialstexten ist nun:
Werden Variablen bei clone mitkopiert und alles andere, was da irgendwie eingestellt wird, oder sind die variablen leer und er macht nur, was ggf. in __clone steht?

Danke schonmal. :]

netcup.de Warum gibt es hier Werbung?
milahu milahu am 17.04.06 18:55

Gegenfrage: Würde die Funktion "clone" heißen, wenn nicht das komplette Objekt mit seinen Attributen kopiert werden würde? (:

Nachzulesen wäre der Spaß - wie immer - im Manual.

Dustwolf Dustwolf am 17.04.06 21:51

Da hab ich es auch nachgelesen. Aber irgendwie schaue ich mir dann mal andere Scripte an und stelle ganz schnell fest, entweder die fuschen da rum, oder man kann mit clone noch irgendwie anders neue Instanzen erstellen.

Wie schaffe ich es denn, dass sich eine Class in sich selbst erstellen kann. Also ohne "klonen". :D

milahu milahu am 17.04.06 22:37

Vielleicht mit clone $this?

Dustwolf Dustwolf am 18.04.06 11:44

Irgendwie will der nit so, wie ich will.
Ich lege nun in der (private) Variablen objekte ein Objekt an:

protected function elemente(){
# Die Funktion legt ggf. Unterobjekte an und setzt somit Vorlagen in Templatelisten um.
preg_match_all('#<!--\s*ANFANG\s+(.*)\s*-->(.*)<!--\s*ENDE\s+(\\1)\s*-->#s',
$this->template,
$elemente);
for($i = 0; $i < count($elemente[1]); $i++){
$this->objekte[$elemente[1][$i]] = clone($this);
if(is_object($this->objekte[$elemente[1][$i]])) echo 'Object angelegt<br>';
$this->objekte[$elemente[1][$i]]->vorlage($elemente[2][$i]);
$this->template = preg_replace('#<!--\s*ANFANG\s+'.$elemente[1][$i].'\s*-->'.$elemente[2][$i].'<!--\s*ENDE\s+'.$elemente[1][$i].'\s*-->#s',
'{'.$elemente[1][$i].'}',
$this->template);
}
}

Da gibt er mir dann auch immer an: Objekt angelegt. Wenn ich nun aber
public function block($id){
foreach($this->objekte as $key => $value) echo $key.'_'.$value.'<br>';
echo $this->name.'_'.$id; # Verweis auf ein Unterobjekt.
if(is_object($this->objekte[$id]))
return $this->objekte[$id];
else
die('<b>Fehler im Templatesystem:</b><br>Nicht existierendes Element_'.$id.'_ in _'.$this->name.'_ aufgerufen!');
}


aufrufe, dann kennt er angeblich die Objekte nimmer. Per foreach gibt er die zwar aus mit
liste _Object id #2
liste2 _Object id #3

aber dann folgt auch schon
Fehler im Templatesystem:
Nicht existierendes Element_liste_ in _Template_ aufgerufen!


Wieso erkennt er das Objekt als Objekt, aber irgendwie auch nicht? ;(

milahu milahu am 18.04.06 12:07

Seltsam. Und als Referenz?
$a =& clone($b);
oder
$a =& $b->__clone();

Dustwolf Dustwolf am 18.04.06 12:23

Also soll ich $b als get_class() verstehen? Weil ansonsten spuckt er mir ohnehin endlos Fehler aus. Bzw. ne Referenz kann ich doch erst erstellen, wenn das Objekt schon besteht, oder versteh ich das falsch.

Ich versuche mir das wie Delphi-classes vorzustellen, weil wir die in der Schule schon gelernt haben... Ggf heißt Referenz hier aber auch was anderes. :D

(Müsste nach dem & nicht ohnehin ein new stehen???)

Michael Michael am 18.04.06 12:51

Nein Referenz heisst hier genau das gleiche - eben ein Zeiger. Allerdings ist eine explizite Zuweisung per Referenz seit PHP5 nicht mehr nötig, da Objetke nun immer als Referenz übergeben werden.

Leider sitze ich gerade beim Arbeiten und kann daher nicht den ganzen Thread lesen... Allerdings sei erwähnt, dass clone viel mehr als eine neue Instanz erstellt, es werden ja auch die Werte der Attribute kopiert. Eine neue Instanz erstellst du ganz normal mit new. Es spricht auch nichts dagegen innerhalb einer Klasse neue Instanzen derselben zu erstellen und diese in Attributen zu speichern.

Wenn ich dein Codestück richtig interpretieren, suchst du in deinem Templatesyste nach "Untertemplates" und willst diese als Objekt in einem Attribut der übergeordneten Templateklasse speichern. Das klappt dann prima, wenn diese im Konstruktor das Template als String erhält; angenommen deine Templateklasse heisst template dann wäre dies ja einfach so:
$this->objekte[$elemente[1][$i]] = new template($elemente[2][$i]);

Vermutlich ist das Argument aber ein Dateiname. Dann würde ich empfehlen von dieser Klasse zu erben und nur den Konstruktor bzw ggf die Methode zum einlesen zu überschreiben.

Viele Grüße,
Michael

P.S.
$object = &new classname ist gleich $object =& new classename und seit PHP5 identisch mit $obect = new classname
Hier spuckt die Schreibweise mit & sogar eine Warnung oder Notice aus

Dustwolf Dustwolf am 18.04.06 13:39

Ajo, also das ist auch so angedacht. Mitlerweile habe ich clone soweit ausgetestet. :D

Also, zu start lege ich per __construct eine Templateklasse an, wobei in $template der Dateiinhalt gelesen wird, $inhalt die Platzhalter und Inhalte bekommt und $objekte die Subtemplates. Also zum Beispiel eine Tabellenzeile zum dublizieren.

Wenn ich so ein Untertemplate habe, verwende ich nun clone($this) und setze dann die Variablen von oben per unset auf ''. Also nix. ;-)
Dann hau ich statt wie im constructor den Inhalt (hier mal die Tabellenzeile) wieder in die $template und lasse wieder nach Untertemplates suchen.

Sprich es werden solange Objekte ineinander verschachtelt, bis alle Ebenen abgearbeitet sind.

Die oben genannte Tabellenzeile würde also in:
$this->objekte['tabellenzeile'] als eigentständiges Objekt sitzen. Dieses würde ich dann per Ausgabe in die übergeordnete Templateclass einsetzen. Also quasi ich lasse das Unterobjekt eine Ausgabe vornehmen und packe diese im entsprechenden Platzhalter in $this->inhalt.
Soweit so gut. Laut Ausgabe von PHP hat er die Objekte auch brav erstellt und der Inhalt stimmt auch.

Wenn ich nun aber die Tabellenzeile füllen will und dazu auf das Objekt im Templateobjekt verweise, dann kommt es zum Fehler.
Aber laut Theorie sollte es doch genügen, per return das $this->objekte[...] an eine Variable im eigentlichen Seitenscript zu übergeben.
Also, dass ich quasi das Objekt der Tabellenzeile durch die eigentliche Template-Class durch direkt anspreche.

Ich bin irgendwie ratlos. Vllt. findet ihr ja einen Fehler in meiner theoretischen Lösung. Ansonsten poste ich heut nachmittag mal mein ganzes Templatesystem. So lang ist das nit.

Michael Michael am 18.04.06 14:06

Quote
Original von Dustwolf
Wenn ich so ein Untertemplate habe, verwende ich nun clone($this) und setze dann die Variablen von oben per unset auf ''. Also nix. ;-)


Genau dafür ist clone nicht gedacht ;)
Prinzipiell ist deine Idee super, sinnvoll objektorientiert. Aber warum erstellst du nicht anstelle mittels clone mit new wirklich neue Instanzen mit leeren Attributen? Das wäre viel passender.

Michael

Dustwolf Dustwolf am 18.04.06 15:36

Also, ich konnte das reparieren. Der Fehler lag an unerwarteter Stelle: Beim Regexausdruck. Der hat da unbemerkt nen Leerzeichen mit reingezogen, dass man bei der Standardschriftgröße und -farbe im FF nit so leicht erkennen konnte. Er hat quasi das Objekt liste + Leerzeichen gestartet und ich habs mit liste ohne Leerzeichen am Ende versucht.

Die sollten da nen auto-trim() einbauen.^^

Trotzdem Danke und ich habe das clone nu trotzdem rausgeworfen. Jetzt ist zwar meine construct-Funktion sehr groß geworden, aber das passt schon. :D

Michael Michael am 18.04.06 15:55

Falls du daran interessiert OOP weiter zu vertiefen, könntest du über folgenden sinnvollen Schritt nachdenken:

Du benutzt für die neuen Unterobjekte (,die du jetzt nicht mehr per clone erstellst ;)) eine neue Klasse, die von der "normalen" erbt und nur den Konstruktor überschreibt. Auf diesem Wege müsstest du im Konstruktor nicht beide Fälle abfangen sondern hättest dies durch die Klassenstruktur geregelt.

Viele Grüße,
Michael

Dustwolf Dustwolf am 18.04.06 16:22

Das wär mal zu überlegen. Ich werde die nächsten Tage über noch einige andere Objekte schreiben und dann mal schauen, ob ich da noch das ein oder andere dran abrunde.
Jetzt kommen erstmal Datenbank- und Text-Objekte dran. Dann noch nen Counter/Statistik und ne Stoppuhr.
Dann hab ich alle Basisfunktionen für meine Websites in Classes gepackt und muss die nit immer neu schreiben und anpassen. Das wird nu alles superdynamisch.

Haste außer dem Manual noch nen gutes Tutorial zu classes? Ich muss mal schauen, eventuell hab ich da noch eins gesehen, wo ich das mit den Regex nachgelesen habe. Weil wenn ich das nu schon mache, dann will ich da nicht noch Fehler und umständliche Codestücke reinbauen. :D

Creative Commons Lizenzvertrag
Alle Inhalte des Webstatt-Archivs stehen unter einer Creative Commons Namensnennung - Weitergabe unter gleichen Bedingungen 3.0 Unported Lizenz.

Impressum & Kontakt