Fatal error: Cannot redeclare class ... BB-Code-Klasse
Erri
- php
Hallo,
ich erhalte in meinem Gästebuch folgende Fehlermeldung:
Fatal error: Cannot redeclare class bbcode in /../../bbcode.inc.php on line 15
ich lese in meinem Gästebuch die Einträge per while-Schleife aus der Datenbank.
Um die Einträge (BB-Code, Silies) zu ersetzen, nutze ich die Parserklasse von Christian Seiler. Diese Binde ich in die While-Schleife ein.
while (...) {
:
include('replace.php');
:
:
:
}
In dieser replace.php befindet sich wiederum die eingebundene Klasse sowie die definierten BB-Codes.
Bei google bin ich auf einen Hinweis gestoßen, dass man in Schleifen statt "include" "include_once" verwenden soll.
Wenn ich include_once verwende, erscheint zwar die Fehlermeldung nicht mehr, allerdings wird dann in allen Einträgen, die per "while" aus der Datenbank ausgelesen werden, derselbe Inhalt angezeigt. Immer der Inhalt des Beitrages, welcher zuletzt hinzugefügt wurde.
Ich habe mal den Quelltext online gestellt: (nur wichtige Auszüge)
Viele Grüße und Vielen Dank,
Erri
Hello,
Die Klasse enthält ja erstmal die Definition der Methoden und Eigenschaften. dabei handelt es sich um den fertig ausfüllten Prototypen der Klasse. Um damit nun in einer Schleife zu arbeiten, musst Du ggf. mehrere Instanzen (Kopien) dieses "Musters" ziehen und initialisieren. Das findet i.d.R. automatisch durch den Construktor der Klasse statt.
Das Include_Once(Klassendefinition) sollte also nur einmal stattfinden, und zwar genau dann, wenn man weiß, dass man die Methoden der Klasse nutzen will. Das kann durchaus durch ein bedingtes include() erfolgen.
Warum sollte man sich auch Klassen hinzuladen, die im Script nicht benötigt werden.
Du Nutzung findet dann ebern z.B. Durch
$__user = new cUser;
statt.
unter $__user->methode oder
unter $__user->eigenschaft wenn öffentlich zugänglich
sind die Methoden und Eigenschaften dann ansprechbar.
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
Hi Tom,
Das Include_Once(Klassendefinition) sollte also nur einmal stattfinden, und zwar genau dann, wenn man weiß, dass man die Methoden der Klasse nutzen will...
Mache ich das nicht an dieser Stelle, wo ich die replace.php include?
include_once (ROOT.'/[....]/replace.php');
//include (ROOT.'/[....]/replace.php');
Oder meinst du die Includes in der replace.php?
include (ROOT.'/[...]/bbcode/bbcode.inc.php');
include (ROOT.'/[...]/bbcode/url_syntax.php');
Warum sollte man sich auch Klassen hinzuladen, die im Script nicht benötigt werden.
Das verstehe ich nicht ganz. Ich benötige doch diese Klasse im Script, also muss ich mir diese doch laden?
Viele Grüße und Vielen Dank,
Erri
hi,
Warum sollte man sich auch Klassen hinzuladen, die im Script nicht benötigt werden.
Das verstehe ich nicht ganz. Ich benötige doch diese Klasse im Script, also muss ich mir diese doch laden?
ja, aber nur genau _ein mal_ - ansonsten kommt eben die fehlermeldung, die du beobachtet hast.
das _benutzen_ eines objektes ist doch wohl etwas ganz anderes, als das einbinden seiner _deklaration_.
gruß,
wahsaga
Hi wahsaga,
Das verstehe ich nicht ganz. Ich benötige doch diese Klasse im Script, also muss ich mir diese doch laden?
ja, aber nur genau _ein mal_ - ansonsten kommt eben die fehlermeldung, die du beobachtet hast.
Ich habe die Klasse doch nur ein einziges mal eingebunden, oder wird diese durch die Schleife mehrmals eingebunden?
Ich hatte vorhin geschrieben, dass die Fehlermeldung verschwindet, wenn ich "include_once" verwende. Aber warum wird dann (bei "include_once") in jedem Beitrag, der aus der Datenbank ausgelesen wird der Inhalt des Beitrages angezeigt, welcher zuletzt im Gästebuch hinzugefügt wurden ist?
Ich weiß nicht so richtig, wie ich dies lösen kann.
Viele Grüße und Vielen Dank,
Erri
hi,
Ich habe die Klasse doch nur ein einziges mal eingebunden, oder wird diese durch die Schleife mehrmals eingebunden?
wenn in replace.php die deklaration dieser klasse ist, wird sie natürlich durch ein include innerhalb deiner while-schleife erneut deklariert - was eben die fehlermeldung erzeugt.
Ich hatte vorhin geschrieben, dass die Fehlermeldung verschwindet, wenn ich "include_once" verwende.
ja, weil dann der interpreter automatisch darauf achtet, die datei nur ein einziges mal einzubinden.
Aber warum wird dann (bei "include_once") in jedem Beitrag, der aus der Datenbank ausgelesen wird der Inhalt des Beitrages angezeigt, welcher zuletzt im Gästebuch hinzugefügt wurden ist?
du unterscheidest offenbar immer noch nicht richtig zwischen der einbindung der deklaration des objectes, und seiner _benutzung_. dazu hatte dir Tom doch in https://forum.selfhtml.org/?t=90953&m=546222 schon was geschrieben.
irgendwie scheint da grundlagenwissen über den umgang mit objekten zu fehlen - da solltest du erst noch mal ein wenig im manual nachlesen gehen.
gruß,
wahsaga
Hi wahsaga & Tom,
du unterscheidest offenbar immer noch nicht richtig zwischen der einbindung der deklaration des objectes, und seiner _benutzung_. dazu hatte dir Tom doch in https://forum.selfhtml.org/?t=90953&m=546222 schon was geschrieben.
Das war mein eigentliches Problem.
irgendwie scheint da grundlagenwissen über den umgang mit objekten zu fehlen - da solltest du erst noch mal ein wenig im manual nachlesen gehen.
Ich habe mir soeben nocheinmal etwas über OOP angeschaut...
Das hatte ich zwar schon einmal getan, aber anscheint etwas falsch verstanden.
Ich habs jetzt hinbekommen indem ich nur das Objekt $bbcode innerhalb der while-Schleife erzeugt habe und somit auch die Eigenschaften innherhalb der Schleife zuweise.
Die Klasse mit den Methoden habe ich vor der while Schleife deklariert.
Ich hoffe, dass ich es diesmal besser verstanden habe.
Ich habe Methoden, Eigenschaften und Objekte irgendwie verwechselt.
(Man lernt eben nie aus *ggg*)
Nocheinmal vielen Dank an euch.
Viele Grüße und Vielen Dank,
Erri
Hello,
nun solltest Du aber auch nicht vergessen, die in der Schleife erzeugten Objekte wieder zu vernichten, wenn sie ihre Schuldigkeit getan haben. Sonst läufst Du bei längeren Schleifen nämlich auf einen Hammer.
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
Hi ,
nun solltest Du aber auch nicht vergessen, die in der Schleife erzeugten Objekte wieder zu vernichten, wenn sie ihre Schuldigkeit getan haben. Sonst läufst Du bei längeren Schleifen nämlich auf einen Hammer.
Kannst du mir sagen, mit welcher Funktion ich das Objekt $bbcode löschen kann? Ich habe gegooglet und hier (http://www.php.net/manual/de/ref.classobj.php) geschaut, aber da finde ich nix von Objekte löschen.
Viele Grüße und Vielen Dank,
Erri
Hi Tom,
Kannst du mir sagen, mit welcher Funktion ich das Objekt $bbcode löschen kann? Ich habe gegooglet und hier (http://www.php.net/manual/de/ref.classobj.php) geschaut, aber da finde ich nix von Objekte löschen.
Ich habe jetzt einmal probiert, nach der while-Schleife mit "unset($bbcode);" das Objekt zu löschen.
Funktioniert das so oder würde das nur bei Variablen funktionieren?
Viele Grüße und Vielen Dank,
Erri
Hello,
Ich habe jetzt einmal probiert, nach der while-Schleife mit "unset($bbcode);" das Objekt zu löschen.
Funktioniert das so oder würde das nur bei Variablen funktionieren?
Man muss hier unterscheiden, wann man die Instanz wieder loswerden will und wann man einen echten Destructor benötigt. Der Destructor wird üblicherweise dann aufgerufen, kurz bevor ein Programm stirbt oder ein Gültigkeitsbreich verlassen wird. Es sind noch Dinge zu erledingen, und außerdem soll die Instanz sich selber aus dem Speicher entfernen.
Das funktioniert bei Interpreter-Sprachen sowieso meistens anders. Da ist die Instanzerzeugung vollständig Bestandteil (Kind) des Runtime und bekommt von diesem den Speicher zugeteilt. Wenn man dann eine Instanzvariable (Zeiger auf die Instanz) wieder aus der Variablen liste entfernt, wird automatisch der gesamte daran angekoppelte Baum aus dem Speicher entfernt, bzw. wieder freigegeben. Eine Klasse kann man sich in PHP auch wie ein Multiarray vorstellen. In den Blättern sitzen die Eigenschaften und Funktionsnamen. Die Funktionen selber sind ohnehin im "Table of Functions" referenziert und damit linearisiert.
Es müsste in der Schleife dann auch keine Probleme machen, eine Instanzvariable einfach mit einer neuen Instanz zu überschreiben, sie für eine neue Instanz wiederzuverwenden, da PHP das ja bai Arrays auch zulässt. Die Beeitigung der alten Instanz findet (hoffentlich) automatisch statt.
Anders in einer Basisorientierten Hochsprache, wie z.B. Pascal.
Wenn ich da mit new(pointer) einen Speicherbereich allokiere und dann einfach nochmal mit new(pointer) dieselbe Instanzvariable nochmals belege, ist der Speicherbereich, den ich das erste mal besorgt hab, verloren Unter http://www.schoenleber.org/pascal/pascal2-06.html ist eine sehr schöne Erklärung zu finden. Man darf dann vor einer Neubelegung das dispose(pointer) nicht vergessen.
Wenn sichergestellt ist, dass in der Schleife immer dieselbe Instanzvariable benutzt wird und PHP sich zuverlässig um die Beseitigung der alten Instanz kümmert, musst Du in der Schleife gar nichts weiter tun und am Schleifenende nur die letzte Instanz mit unset() entfernen, wenn Du sie nicht mehr benötigst.
Die Klassendefinition selber wirst Du mWn leider gar nicht wieder los. Wenn das Script also länger läuft und mehree Aufgaben zu erledigen hat, könnte bei mehrfachen Includes schon ein Memory Overflow Error auftreten. Dadurch, dass die meisten Scripte aber nur 8ms (oder auch mal 30s) leben, wird der Speicher immer wieder automatisch freigegeben für andere Scripte.
Harzliche Grüße aus http://www.annerschbarrich.de
Tom
Hello,
Das Include_Once(Klassendefinition) sollte also nur einmal stattfinden, und zwar genau dann, wenn man weiß, dass man die Methoden der Klasse nutzen will...
Mache ich das nicht an dieser Stelle, wo ich die replace.php include?
Genau an dieser Stelle lädst Du die Definitionen dazu. Von diesem Zeitpunkt an stehen Dir die Methoden der Klasse zur Verfügung. Wenn ich schrieb, dass man nur Klassen hinzuzuladen braucht, die man auch nutzen will, dann bezieht sich das auf sogenannte "Multi Purpose Scripts", also zentrale Steuerscripte, die im Prinzip nur die Userinteraktion auswerten (Submit-Buttondruck -> Request) und dann darauf die passende Aktion zusammenstellen und ausführen. Solch ein Script benötigt immer nur die Includes, die für die Abarbeitung des Requests notwendig sind. Es wäre einfach zu teuer (Speicherplatznutztung) immer alles zu laden, was es gibt.
include_once (ROOT.'/[....]/replace.php');
Harzliche Grüße aus http://www.annerschbarrich.de
Tom