Beim laufenden Projekt bin ich auf zwei eigenartige PHP-Eigenheiten gestoßen, die zwar keine Fehler sind, aber trotzdem unerwartetes Verhalten darstellen:
Freestyle-Modulus
Die erste Eigenartigkeit ist der Modulo-Operator (%), der sich normalerweise so definiert:
Modulus von a und b = Divisionsrest von a durch b
Also ist 30 % 15 = 0 (weil 15 in 30 ohne Rest enthalten ist).
Was aber ist 31 % 15,5? Natürlich auch 0, weil 15,5 * 2 = 31.
Aber PHP liefert nicht 0, sondern 1!
Der Grund steht in der englischen Version des Onlinehandbuchs (nicht in der deutschen!):
Operands of modulus are converted to integers (by stripping the decimal part) before processing.
Also macht PHP aus 31 % 15.5 -> 31 % 15 mit Ergebnis 1.
Was das für einen Sinn hat, besonders wenn man zum Beispiel bestellte Mengen auf ganze Verpackungseinheiten prüfen muss, sei dahingestellt.
Einmal nichts, bitte
Auch die count-Funktion sorgte bei mir diesmal für Kopfzerbrechen.
Diese Funktion dient dazu, die Anzahl der Elemente eines Arrays zu ermitteln. Was liefert sie wohl zurück, wenn man keinen Array übergibt?
count('hase') liefert:?
Nein, nicht etwa false, weil 'hase' kein Array [oder etwas anderes "Countables"] ist! Aus irgendeinem Grund sieht sich PHP verpflichtet, solche Fehlbenutzungen zu überspielen. Bei der Implementierung ist man davon ausgegangen, dass der Programmierer in diesem Fall keinen Fehler, sondern den Rückgabewert 1 erwartet. "1" deswegen, weil 'hase' ja ein Element ist, konkret 'hase' == 1 String.
Mir fällt kein Beispiel ein, wo das sinnvoll wäre. Eher erschwert es die Fehlersuche. Besonders krass wird es bei booleschen Werten:
count(false) == 1
Warum? Weil false == 1 boolescher Wert. Somit kann es zu üblen und schwer auffindbaren Fehlern kommen wie zB:
// alle artikel mit schlüssel 'key' aus der DB lesen
$liste = read_liste_from_database($_REQUEST['key']);
// alle artikel ausgeben
for($i=0; $i<count($liste); $i++)
echo "Element ".($i+1).": ".$liste[$i]."<br />";
Wenn aber read_liste_from_database() einen key erhält, zu dem es keine Artikel gibt?
Dann liefert es idealerweise einen Leer-Array (array()). Oder aber false, was auch nicht ganz abwegig ist.
count($liste) ist dann aber 1, und drum sehen wir die Ausgabe:
Element 1:
Solche ausdrucksstarken Ausgaben hat wahrscheinlich jeder PHP-Programmierer schon einmal irgendwo gesehen ...
Natürlich sollte man auf eine gewisse Genauigkeit bei den Datentypen achten. Aber wenn dem Programmierer dabei einmal ein Fehler passiert, nimmt man an, PHP würde den so gut wie möglich ausgleichen (beim impliziten Casten klappt das ja auch gut). Was hier allerdings ausnahmsweise nicht geschieht. Übrigens: Eine Ausnahme von der Regel, dass count([nicht-Array]) == 1, ist NULL. Bei NULL, dachten die Entwickler wohl, kann man beim besten Willen nicht unterstellen, dass es irgendeinen Sinn ergäbe, "1" herauszulesen.