cannot redeclare funktion()
Thomas Schmieder
- php
Hallo,
nun haben wir uns mal wieder aufgehängt...
Die Fakten:
Funktionsbibliothek "funcLib.inc.php" wird am Anfang der Seite einmalig durch include() eingebunden.
Die Lib enthält eine Funktion get_pagerights(), die ihrerseits wieder Funktionen enthält. Das hat in PHP keine Auswirkung. Es gibt keine private functions, weiß ich. Die Lib hat bisher funktioniert.
Nun haben wir eine weitere Funktion eingebaut "get_tree()", die ein Array erzeugt, in dem unsere jeweils aktuelle Seitenhierarchie vom Wurzelpunkt bis zur aufgerufenen Seite eingetragen wird, und die dazugehörigen Rechte ebenfalls. Hierzu wird die Funktion get_pagerights() aufgerufen, die ihrerseits get_show() aufruft.
Das Array ist ein ein ganz schöner Klotz. Das hat bisher allerdings auch nie Probleme bereitet.
Nun meckert aber der Parser und spuckt immer eine Fehlermeldung aus:
cannot redeclare get_show() in Line 517 <-- Das ist die Zeile, an der die Funktion get_show() einmalig deklariert ist.
Wir haben alles untersucht. Ein Redeklarationsfehler ist uns nicht offensichtlich. Woran könnte das noch liegen, dass dieser Parserfehler ausgelöst wird?
Liebe Grüße aus http://www.braunschweig.de
Tom
Funktionsbibliothek "funcLib.inc.php" wird am Anfang der Seite einmalig durch include() eingebunden.
cannot redeclare get_show() in Line 517 <-- Das ist die Zeile, an der die Funktion get_show() einmalig deklariert ist.
Wir haben alles untersucht. Ein Redeklarationsfehler ist uns nicht offensichtlich.
Nicht, daß es daran liegen muß, aber Funktionsbibliotheken sollten besser immer mit include_once() importiert werden. Vielleicht wird Eure "funcLib.inc.php" ja doch irgendwie in zwei Dateien angesprochen und dementsprechend zweimal importiert.
Gruß,
soenk.e
Hallo
Funktionsbibliothek "funcLib.inc.php" wird am Anfang der Seite einmalig durch include() eingebunden.
cannot redeclare get_show() in Line 517 <-- Das ist die Zeile, an der die Funktion get_show() einmalig deklariert ist.
Nicht, daß es daran liegen muß, aber Funktionsbibliotheken sollten besser immer mit include_once() importiert werden. Vielleicht wird Eure "funcLib.inc.php" ja doch irgendwie in zwei Dateien angesprochen und dementsprechend zweimal importiert.
Wenn die Funktionsbibliothek unbedingt notwendig ist, sollte sie mit
require_once()
eingebunden werden.
Gruss,
Vinzenz
Hallo Soenke,
danke für den Tipp. Aber daran liegt es nicht. Es wird immer verrückter. Wir sind dem Übel auf der Spur.
Es liegt an einer Array-Deklaration.
Mir ist eben ganz bitter bewusst geworden, dass PHP maximal zweidimensionale Arrays hat. Wenn man versucht, eine dritte Dimension anzulegen, passiert irgendein Blödsinn. Er schreibt dann wild im Speicher umher...
Ist das bei neueren Versionen immer noch so? Wir haben hier noch 4.0.4
Liebe Grüße aus http://www.braunschweig.de
Tom
Hallo Tom,
Es liegt an einer Array-Deklaration.
Mir ist eben ganz bitter bewusst geworden, dass PHP maximal zweidimensionale Arrays hat. Wenn man versucht, eine dritte Dimension anzulegen, passiert irgendein Blödsinn. Er schreibt dann wild im Speicher umher...
<zitat src="Programming PHP" author="Rasmus Lerdorf & Kevin Tatroe" translation="free">
Die Werte eines Arrays können selbst wiederum Arrays sein. So können Sie leicht mehrdimensionale Arrays erstellen
$row_0 = array(1,2,3);
$row_1 = array(4,5,6);
$row_2 = array(7,8,9);
$multi = array($row_0, $row_1, $row_2);
Auf Elemente eines mehrdimensionalen Arrays kann über mehrere [] zugegriffen werden:
$value = $multi[2][0];
Um ein Nachschlagen in einem mehrdimensionalen Array zu interpolieren, muss das gesamte Array in geschweifte Klammern eingeschlossen werden.
echo "The value at row 2, column 0 is {$multi[2][0]}\n";
Vergißt man die geschweiften Klammern, so ergibt sich folgende Ausgabe:
The value at row 2, column 0 is Array[0]
</zitat>
Natürlich ist es auch möglich, dass die Elemente eines Arrays zweidimensionale Arrays sind, dann hast Du ein dreidimensionales Array ...
Probiere es mit einem erweiterten einfachen Beispiel aus.
Gruss,
Vinzenz
Hi Tom!
danke für den Tipp. Aber daran liegt es nicht. Es wird immer verrückter. Wir sind dem Übel auf der Spur.
ist doch schon mal was ;-)
Es liegt an einer Array-Deklaration.
wie sieht die aus?
Mir ist eben ganz bitter bewusst geworden, dass PHP maximal zweidimensionale Arrays hat. Wenn man versucht, eine dritte Dimension anzulegen, passiert irgendein Blödsinn. Er schreibt dann wild im Speicher umher...
Du bist sicher das Du auch _PHP_ installiert hast? Hast Du Dein Archiv mal mit dem md5-String unter http://www.php.net/downloads.php verglichen? Zumindest passieren mir nie solche Sachen. Was vielleicht auch daran liegt das Deine Version ziemlich veraltet ist, mit _sehr_ vielen Bugs. Wenn Du unter bugs.php.net nachfragen würdest ob das Problem bekannt sei, würdest Du hören "erst auf neuste Version updaten, wenn der Fehler dann noch auftritt dann reden wir weiter". Und wenn man sich mal anguckt wieviele Bugs mit jedem neuen Release gefixt werden, habe ich persönlich kein großes Vertrauen in alte PHP Versionen, schon gar nicht in PHP < 4.1.2
Ich vermute eigenlich das Du weißt wie man in PHP einen Array deklariert, aber nur um sicherzugehen, Du verwendest multidimensionale Arrays genau so wie unter http://de3.php.net/manual/de/language.types.array.php beschrieben, richtig? Was machst Du genau und was macht Dich so sicher das es damit zu tun hat? Und woher weißt Du was PHP beim Erstellen eines Arrays genau macht?
Viele Grüße
Andreas
Mir ist eben ganz bitter bewusst geworden, dass PHP maximal zweidimensionale Arrays hat. Wenn man versucht, eine dritte Dimension anzulegen, passiert irgendein Blödsinn. Er schreibt dann wild im Speicher umher...
Ist das bei neueren Versionen immer noch so? Wir haben hier noch 4.0.4
Mit Verlaub, 4.0.4 ist ja nun wirklich von Anno Dazumal. Ab und an sollte man sich schon um neue Versionen kümmern :) Ich für meinen Teil verwurste hier jedenfalls mit 4.2.3 sechsdimensionale Felder mit einigen hundert Einträgen - problemlos.
Gruß,
soenk.e
Hallo Soenke,
Mit Verlaub, 4.0.4 ist ja nun wirklich von Anno Dazumal. Ab und an sollte man sich schon um neue Versionen kümmern :) Ich für meinen Teil verwurste hier jedenfalls mit 4.2.3 sechsdimensionale Felder mit einigen hundert Einträgen - problemlos.
Ja, da ist was dran. Muss aber eine Komplettrenovierung des ganzen Servers werden.
Den Array-Fehler haben wir gefunden. Es ist nicht gestattet, eine implizite Dimensions-Definition vorzunehmen, wenn das Element bereits mit einem Skalar belegt ist. Und "false" ist eben einer.
Das muss man dann erst mit =array() überschreiben, dann kann man anschließend neue Arrayelemente einfügen.
Den anderen Fehler haben wir zwar inzwischen eingekreist, aber noch nicht identifizieren können. Ist so ein ähnliches Gefühl, wie bei C-Programmen in mehrfach verzeigerten Zuweisungen zu finden :-((
Liebe Grüße aus http://www.braunschweig.de
Tom
Hi Tom,
Mit Verlaub, 4.0.4 ist ja nun wirklich von Anno Dazumal. Ab und an sollte man sich schon um neue Versionen kümmern :) Ich für meinen Teil verwurste hier jedenfalls mit 4.2.3 sechsdimensionale Felder mit einigen hundert Einträgen - problemlos.
Ja, da ist was dran. Muss aber eine Komplettrenovierung des ganzen Servers werden.
Ich bringe Samstag meine Debian(3.0.r1)-Images mit, wenn es dir recht ist. Beschnüffel die halt erstmal, wenn du deine SuSE 7.3 nicht gleich zur Hölle schicken möchtest, auch wenn sie es durchaus verdient ;-)
Grüße,
Fabi
Hi Fabi,
wäre nett, wenn Du Copies vom ganzen Packet (inclusive des neueren Apache, der PHP-Version und der MySQL) mitbringen könntest. Bekommst von Mir dann leere Rohlinge.
Wir werden dann schnellstens einen neuen Server aufbauen.
Liebe Grüße aus http://www.braunschweig.de
Tom
Hallo!
wäre nett, wenn Du Copies vom ganzen Packet (inclusive des neueren Apache, der PHP-Version und der MySQL) mitbringen könntest. Bekommst von Mir dann leere Rohlinge.
Empfehle Apache 1.3.27, PHP 4.3.0, MySQL 3.23.55 in Zusammenarbeit mit PHPA 1.3.4 (http://www.php-accelerator.co.uk/)
Grüße
Andreas
Hi Tom, Andreas,
wäre nett, wenn Du Copies vom ganzen Packet (inclusive des neueren Apache, der PHP-Version und der MySQL) mitbringen könntest. Bekommst von Mir dann leere Rohlinge.
In Ordnung. Ich erwänhte bereits die geilen Möglichkeiten, Debian online upzudaten? Naja, auf jeden Fall kann das (bei einer schnellen Leitung) on the fly geschehen und hinterher muss man nur den webserver bzw. den betroffenen service restarten... Ist doch was, oder? =)
Empfehle Apache 1.3.27, PHP 4.3.0, MySQL 3.23.55 in Zusammenarbeit mit PHPA 1.3.4 (http://www.php-accelerator.co.uk/)
ACK, hab ich auch laufen, ist bei Debian alles dabei, PHP 4.3.0 muss ich noch besorgen, bei der Distri ist bloß 4.1.2 (warum eigentlich?) dabei...
Fabian
Hallo Andreas,
danke für die Tipps.
Empfehle Apache 1.3.27, PHP 4.3.0, MySQL 3.23.55 in Zusammenarbeit mit PHPA 1.3.4 (http://www.php-accelerator.co.uk/)
Sind da irgendwelche Bugs bekannt, die ich beachten muss, wenn wir das in die Produktion nehmen?
Für die Eigenverwendung gibt es da ja hoffentlich auch keine Lizenzbeschränkungen, oder?
Habe mich nun endlich zu einem neuen Access-Provider durchgerungen und werde heute Nacht de Auftratg faxen. dann haben wir zwar erstmal nur 2,3MBit sDSL über Draht aber mit CU-Redundanz und können dadurch auf 4,6 aufrüsten.
Ich siche noch Mitnutzer (Serverhousing). Wir bekommen einen Flatpreis.
Liebe Grüße aus http://www.braunschweig.de
Tom
Hi Tom!
Empfehle Apache 1.3.27, PHP 4.3.0, MySQL 3.23.55 in Zusammenarbeit mit PHPA 1.3.4 (http://www.php-accelerator.co.uk/)
Sind da irgendwelche Bugs bekannt, die ich beachten muss, wenn wir das in die Produktion nehmen?
Für die Eigenverwendung gibt es da ja hoffentlich auch keine Lizenzbeschränkungen, oder?
IMHO gar keien BEschränkung, absolut frei und von der Performance absolut auf dem gleichen Level wie der teure Zend-Cache, dazu noch den Vorteil das es keinen Einfluß auf PHP-Scripte hat - im Gegensatz zum Zend-Cache. Auf der Seite steht ne ganze Menge, auch viele Performance-Tests. Ich habe es noch nicht laufen, bin gerade dran. Aber ich habe mich auch einer der PHP-Listen umgehört, da haben den auch einige Verwendet, ohen jegliche Probleme und nur gutes drüber gesagt - außer dass er nur mit Apache 1 läuft, aber den sollte man sowieso _UNBEDINGT_ verwenden, Apache 2 hat absolut 0 Vorteile, da er nur mit prefork vernünftig läuft, und prefork ist eigentlich nur ein Kompatibilitäts-Moduls zum Apache 1, man hat nur die ganzen Nachteile des Apache 2, keinen seiner Vorteile. Und das wird noch eine ganze Zeit so bleiben, erst wenn Apache stabil im perchild-Modus läuft wird sich da was ändern.
Soviel dazu.
Neuste Version von MySQL sollte klar sein, PHP 4.3.0 läuft IMHO auch sehr stabil, hat viele neue Features und _sehr_ viele Bug-Fixes.
Ich habe jetzt eine ganze Zeit damit verbracht die obigen Komonenten vernünftig unter meinem RedHat Linux 8.0 zu installieren. RedHat hatte standardäßig nur Apache 2.0.40 und auch PHP 4.1.2 dabei, was sehr unbefriedigend war.
Ich habe jetzt alles kompiliert, Apache mit folgenden Modulen
Compiled-in modules:
http_core.c
mod_env.c
mod_log_config.c
mod_mime.c
mod_negotiation.c
mod_status.c
mod_autoindex.c
mod_dir.c
mod_asis.c
mod_actions.c
mod_userdir.c
mod_alias.c
mod_rewrite.c
mod_access.c
mod_auth.c
mod_setenvif.c
mod_ssl.c
mod_php4.c
Ich verwende kein CGI da ich alleine den Server nutzen werde.War ein ganz schöner Akt, habe mir auch neuste Versionen von
openssl
zlib
jpeg
png
mod_ssl
installiert.
PHP-Module habe ich auch alle mit in den httpd mit einkompiliert.
Was mir noch fehlt ist mod_perl und halt der PHP-Accelerator. Dann funktioniert alles wo wie ich will. Bin dabei mit ein schönes Bash-Scrpt zu schreiben, womit ich später alles auf einmal installieren kann.
Werde aber noch mehr rausschmeißen, das nur die Module verfügbar sind, die ich tatsächlich verwende.
Falls es Dich interessiert, bisher siehts so aus:
cd ~
tar zvxf apache_1.3.27.tar.gz
tar zvxf mod_ssl-2.8.12-1.3.27.tar.gz
tar jxvf php-4.3.0.tar.bz2
tar zvxf openssl-0.9.7.tar.gz
cd openssl-0.9.7
./config --prefix=/usr/local/openssl-0.9.7 no-idea
make depend
make
make test
make install
cd ../mod_ssl-2.8.12-1.3.27
./configure --with-apache=../apache_1.3.27 --with-ssl=/usr/local/openssl-0.9.7
cd ../apache_1.3.27
SSL_BASE=/usr/local/openssl-0.9.7 ./configure --prefix=/usr/local/apache-1.3.27
cd ../php-4.3.0
./configure --prefix=/usr/local/php_a1_4.3.0 --with-png-dir=/usr/local/libpng-1.2.5 --with-gd --enable-gd-native-ttf --with-jpeg-dir=/usr/lib/ --with-png --with-zlib-dir=/usr/lib --with-apache=../apache_1.3.27 --enable-track-vars
make
make install
cd ../apache_1.3.27
./configure --disable-module=cgi --disable-module=include --disable-module=imap --enable-module=rewrite --enable-module=ssl --activate-module=src/modules/php4/libphp4.a --enable-module=php4
make
make certificate
make install
Naja, ich bin noch am rumtesten, bin froh das es erstmal so läuft. Probleme breiten mir noch die Virtual-Hosts, vor allem in Zusammenhang mit SSL. Mal sehen.
Grüße
Andreas
Hallo zusammen,
Die Fehler haben wir nach langem Suchen gefunden:
1.
----------------
Bei der impliziten Deklaration von Mehrdimensionalen Arrays darf keines der Elemente in der Dimensionskette mit einem Skalar vorbelegt gewesen sein.
$person["koerperteil"]["bein"][0]["links"]="zu kurz"; ist möglich.
Wenn aber ein Skalar durch
$person["koerperteil"]="keine"; vorher in das Element geschreiben wurde, funktioniert die obige implizite Neudeklaration nicht mehr. Es gibt dann äußerst ungewöhnliche Ergebnisse. Man kann das Problem durch zwischenzeitliches Überschreiben mit dem richtigen Typ beseitigen.
$person["koerperteil"]="keine";
...
$person["koerperteil"]=array();
$person["koerperteil"]["bein"][0]["links"]="zu kurz"; // nun gehts
2.
----------------
PHP kennt keine Subfunktionen, also Funktionen, die nur Eigentum einer anderen Funktion sind. Alle deklarierten Funktionen sind im gesamten Script erreichbar. Ich habe aber auch bisher nichts darüber gefunden, dass es verboten wäre, trotzdem welche zu schreiben. Das erschien mir manchmal wegen der Zuordnung zu den Funktionen ganz sinnvoll.
Allerdings kann man dann eine solche Funktion mit Subfunktion nur ein einziges Mal im Script aufrufen. Bei der zweiten Verwendung erhält man den beschriebenen Fehler:
cannot redeclare <subfunction()> at zeilennummer in script....
Darauf muss man erst einmal kommen, dass eine Funktion, die einmal geht, kein zweites Mal funktioniert.
Liebe Grüße aus http://www.braunschweig.de
Tom
Hi Tom!
Bei der impliziten Deklaration von Mehrdimensionalen Arrays darf keines der Elemente in der Dimensionskette mit einem Skalar vorbelegt gewesen sein.
$person["koerperteil"]["bein"][0]["links"]="zu kurz"; ist möglich.
Wenn aber ein Skalar durch
$person["koerperteil"]="keine"; vorher in das Element geschreiben wurde, funktioniert die obige implizite Neudeklaration nicht mehr. Es gibt dann äußerst ungewöhnliche Ergebnisse. Man kann das Problem durch zwischenzeitliches Überschreiben mit dem richtigen Typ beseitigen.$person["koerperteil"]="keine";
...
$person["koerperteil"]=array();
$person["koerperteil"]["bein"][0]["links"]="zu kurz"; // nun gehts
Was absolut logisch ist, da Du versuchst ein Element eines Arrays zu verändern, welches es defintiv nicht gibt!
PHP kennt keine Subfunktionen, also Funktionen, die nur Eigentum einer anderen Funktion sind. Alle deklarierten Funktionen sind im gesamten Script erreichbar. Ich habe aber auch bisher nichts darüber gefunden, dass es verboten wäre, trotzdem welche zu schreiben. Das erschien mir manchmal wegen der Zuordnung zu den Funktionen ganz sinnvoll.
Allerdings kann man dann eine solche Funktion mit Subfunktion nur ein einziges Mal im Script aufrufen. Bei der zweiten Verwendung erhält man den beschriebenen Fehler:
cannot redeclare <subfunction()> at zeilennummer in script....
Darauf muss man erst einmal kommen, dass eine Funktion, die einmal geht, kein zweites Mal funktioniert.
In Manual steht das Funktionsnamen nur einmal vorkommen dürfen. Wenn man sich daran hält gibt es IMHO keine Probleme. Wenn ich Funktionen kapseln will verwende ich Klassen. Mit :: lassen sich die Funktionen ja auch aufrufen ohne die Klasse vorher zu instanzieren.
Aufrufen kann an Funktrionen IMHO so oft man will. Wie sieht das Code-technisch aus das Du eine Funktion nur einmal aufrufen kannst?
Grüße
Andreas
Hallo Andreas,
$person ist nicht gesetzt:
$person["koerperteil"]["bein"][0]["links"]="zu kurz"; ist möglich.
Wenn aber ein Skalar durch
$person["koerperteil"]="keine"; vorher in das Element geschreiben wurde, funktioniert die obige implizite Neudeklaration nicht mehr. Es gibt dann äußerst ungewöhnliche Ergebnisse. Man kann das Problem durch zwischenzeitliches Überschreiben mit dem richtigen Typ beseitigen.$person["koerperteil"]="keine";
...
$person["koerperteil"]=array();
$person["koerperteil"]["bein"][0]["links"]="zu kurz"; // nun gehts
Was absolut logisch ist, da Du versuchst ein Element eines Arrays zu verändern, welches es defintiv nicht gibt!
Das ist nicht das Problem. Wenn es nicht existiert, wird es von PHP angelegt. Siehe oben. Aber wenn in der Heirarchie des Elementes auf einer Ebene eines existiert und der Typ passt nicht, dann kann PHP die Typkonvertierung nicht selbständig durchführen.
In Manual steht das Funktionsnamen nur einmal vorkommen dürfen. Wenn man sich daran hält gibt es IMHO keine Probleme. Wenn ich Funktionen kapseln will verwende ich Klassen. Mit :: lassen sich die Funktionen ja auch aufrufen ohne die Klasse vorher zu instanzieren.
Das hatten wir auch eingehalten. Allerdings mochte PHP die "Kapselung" nicht. Hätte ja sowieso keine Wirkung gehabt. War ja nur der Schönheit des Quellcodes wegen.
Liebe Grüße aus http://www.braunschweig.de
Tom
Moin!
In Manual steht das Funktionsnamen nur einmal vorkommen dürfen. Wenn man sich daran hält gibt es IMHO keine Probleme. Wenn ich Funktionen kapseln will verwende ich Klassen. Mit :: lassen sich die Funktionen ja auch aufrufen ohne die Klasse vorher zu instanzieren.
Das hatten wir auch eingehalten. Allerdings mochte PHP die "Kapselung" nicht. Hätte ja sowieso keine Wirkung gehabt. War ja nur der Schönheit des Quellcodes wegen.
Du willst etwas, was z.B. in TurboPascal/Delphi funktioniert: Lokale Funktionen (nicht nur lokale Variable).
PHP ist eine Skriptsprache. Code wird von oben nach unten abgearbeitet, ohne vorher kompiliert zu werden. Auch include() macht Probleme, wenn man es mehrfach aufruft, und im eingefügten Skript Funktionsdefinitionen vorkommen. Insofern ist das Include-Verhalten eigentlich schon übertragbar auf das Verhalten, wenn Funktionsdefinitionen innerhalb von aufgerufenen Funktionen stehen. Die Funktionsdefinition wird bei jedem Funktionsaufruf ausgeführt - genauso wie die Funktionsdefinition bei mehrfachem Include mehrfach ausgeführt wird.
Das Verhalten ist durchaus logisch. Dass du etwas anderes erwartet hättest, und dass es der Codeschönheit helfen würde, lokale Funktionen zu definieren, gilt nicht. ;) Als Bonus kriegst du dafür die Mächtigkeit von eval() und kannst zur Laufzeit neue Funktionen definieren, sofern es nötig ist (allerdings ist selbstmodifizierender Code durchaus eine ziemliche Ekligkeit, die man lieber vermeiden sollte).
- Sven Rautenberg