Mailinglisten-Archive |
Peter Kühn wrote: > > > > Warning: Uninitialized variable or array index or property (checkbox) in > > > oohforms.inc on line 175 > > > > Was steht denn in den genannten Zeilen drin? > > s. den hilfreichen Einwand von Egon: eigentlich sind das keine echten > Fehlermeldungen sondern nur Warnhinweise. Means: irgendwas ist zwar nicht die > reine Lehre, max aber nix - echte böse Fehler lauten folgerichtig irgendwas > mit "Error" (richtig verstanden Egon?) "Richtige" Fehler spucken ein Error. Warning soll auf eine unsaubere oder möglicherweise falsche Programmierung hinweisen. Doch was bedeutet "unsauber"? PHP hat weder streng getypte Variablen noch verlangt es nach einem strengen Verfahren von Definition und Initialisierung, wenn eine neue Variable benötigt wird. +++ Variablen "anmelden" +++ Variablen stehen in PHP "einfach so zur Verfügung". Dies ist vielen Sprachen anders. Eine Variable benötigt Speicher, weshalb viele Sprachen (C, C++, Pascal, Java) die "Anmeldung" einer neuen Variable vorschreiben. Diese Anmeldung besteht aus zwei Schritten. Der Definition zur Festlegung des Typs und der Initialisierung, um der Variablen einen Wert zuzuweisen. Bei der Definition wird ein entsprechend des Typs benötigter Speicherbereich für die Variable reserviert. Bei der Initialisierung werden die zufälligen Daten im reservierten Speicher überschrieben mit dem neuen Wert überschrieben. PHP verfolgt als Skriptsprache wie BASIC (beginners all supposed instructions code) einen anderen Ansatz, den viele Einsteiger einfacher finden. Eine Variable hat (meist) keinen festen Typ und stets einen erwarteten Anfangswert (String "", Zahl 0). Dies verbirgt Komplexität und beseitigt eine der häufigsten Fehlerquellen bei Anfängern. Außerdem entspricht das Verhalten, dem was der Laie erwartet. Will man sauber programmieren muß man also eine Variable mit zur Verwendung "anmelden", etwa so: $elements = array(); # Definition und Initialisierung in einem +++ Typen +++ Der Einsteiger schreibt mal $zahl = "1", mal $zahl = 1 und erwartet, daß beide Varianten das gleiche Ergebnis liefern, wenn man später $zahl mal als mal als Text (PHP: string), mal als Zahl (PHP: integer oder double) verwendet. $zahl = "1"; # $zahl ist ein string echo 'Typ von $zahl: '.gettype($zahl)."<br>\n" # Typ von $zahl ausgeben (string) $zahl = $zahl + 3; # $zahl wie eine Zahl verwenden... funktioniert in PHP genauso wie: $zahl = 1; # $zahl ist ein integer echo 'Typ von $zahl: '.gettype($zahl)."<br>\n" # Typ von $zahl ausgeben (integer) $zahl=$zahl." wie ein String..."; # $zahl wie einen Text behandeln... Um uns diese Toleranz bieten zu können, haben die Core Developer sich entschieden intern jede Variable in allen benötigten Varianten zu speichern. Wenn ich es richtig weiß - bitte korrigiert mich, was den Zeitpunkt der Speicherallozierung betrifft -, wird bei jedem Auftreten einer PHP Variable der benötigte Typ erzeugt und in der internen Hashtable gespeichert. Dies bedeutet, daß bei $zahl = "1" zunächst Speicher für einen String reserviert wird und spätestens nach einem $zahl++ auch für einen Integer. Entsprechend führen massive Typwechsel zu einem geringen Performanceverlust, aber wer würde schon folgendes schreiben (~ -8%) ? for ($i=0; $i<100000; $i++) { $zahl = "1"; $zahl++; } +++ Warum Typen? +++ Streng typisierte Variablen haben auch Vorteile. U.a. verbrauchen sie weniger Speicher, decken Fehlbenutzungen auf und vermeiden solch lustige Dinge wie "===" als Operator, http://www.php.net/manual/language.operators.comparison.php3 . +++ Warnings +++ Speicherallozierung, Typen, all das bleibt dem PHP Einsteiger weitgehend erspart. Würde dem nicht so sein, könnten wir nicht mal ebend $zahl als String und im nächsten Moment als Zahl behandeln. Wir müßten uns genau an die Spielregeln halten. Es wäre auch streng verboten auf Arrayelemente zuzugreifen, die gar nicht existieren. Genau so ein Fall erzeugt obige Warnmeldung. $element = array ("name" => "eissorte", "value" => "Schoko" ); echo $element["checked"]; Dieser Code meldet keinen Error, obwohl das Arrayelement "checked" nicht existiert. C würde bei solch einem Versuch richtig sauer werden. PHP generiert nur bei einem hohen Wert für das Error Reporting ( http://www.php.net/manual/function.error-reporting.php3 ) eine Warnung. "8 = Notices - warnings you can ignore, but sometimes imply a bug (e.g., using an uninitialized variable)", php3.ini-dist > Neu war mir das (zitat Ulf) "Die gesamte PHPLIB spuckt Warnings". > > =>Frage daher: belasten die Warnungen nicht irgendwie letztlich doch die > Maschine (auch wenn sie mit error_reporting=7 unterdrückt werden)? PHP nimmt stets eine Prüfung aller geparsten Variablen vor. Ganz egal, ob die Variable vorher "angemeldet" wurde oder nicht. Die wenigen Zeilen C-Code zur Speicherung eines Warnhinweises sind nicht meßbar. Man könnte geneigt sein, folgende Varianten gegeneinander auszumessen. (1) for ($i=0; $i<100000; $i++) { $daten = array ( "name" => "test" ); $daten["nixda"]++; } (2) for ($i=0; $i<100000; $i++) { $daten = array ( "name" => "test", "nixda" => 0 ); $daten["nixda"]++; } Die zweite Variante ist einen Hauch langsamer, obwohl sie im Gegensatz zur ersten Variante keine Warnings erzeugt. Warum? Per Definition ist es in PHP nicht notwendig Variablen "anzumelden". Es besteht praktisch kein Geschwindigkeitsunterschied zwischen der Verwendung bereits definierter oder bislang undefinierter Variablen. Spürbar ist jedoch der erhöhte Zeitverbrauch des Parsers in der unteren Variante. Sieht der Code wie folgt aus, ist der Geschwindigkeitsunterschied weg. for ($i=0; $i<10000; $i++) { $daten = array(); for ($j=0; $j<20; $j++) $daten["foo_$j"]="foo_$j"; # mit $daten["nix_da"] = 0 tauschen, Zeilenanzahl identisch lassen! $daten["dummie"] = $j; # nicht ändern... $daten["nix_da"]++; } +++ Warum dann Warnings +++ Warnings geben hilfreiche Informationen für das Debuggen der eigenen Skripte. Arbeitet man mit komplexen Arrays und greift durch einen Tippfehler auf ein nicht existierendes Element zu, liefert PHP einen Hinweis. if (""!=$element["namE"]) ... Bei komplexeren Skripten hilft es nicht zuletzt bei der Dokumentation. Gnadenlos werden Variablen gefunden, die zuvor nicht deklariert wurden. Und bei der Deklaration sollte stets ein kurzer Kommentar stehen. Dieser Code ist unglücklich und produziert Warnhinweise: class bla { function get() { return $this->elemente; } } $b = new bla; $elemente = $b->get(); So macht man es besser und kommt prompt ohne Warnungen aus: class bla { var $elemente = array(); # Alle Elemente der OOHForms function get() { return $this->elemente; } } Ulf
php::bar PHP Wiki - Listenarchive