Neulich bin ich bei der Portierung eines PHP-Scripts von meinem Entwicklungs-PC auf den Raspi fast verzweifelt. Eine Ajax-Routine wollte einfach nicht mehr funktionieren.
Nach längerem Debugging fand ich heraus, dass es an einem scheinbar fehlenden POST-Parameter lag. Nur: auf dem PC funktionierte dieses Script einwandfrei, nur auf dem Raspi war der Parameter leer.
Inhalt des fraglichen Parameters ist eine EAN-Nummer, die 8- oder 13-stellig ist, also theoretisch zwischen 0 und 9.999.999.999.999 liegt.
Natürlich validiere ich alle Ajax-Parameter brav mit der filter_input-Funktion. Die EAN-Nummer überprüfe ich mit dem FILTER_VALIDATE_INT Flag, also
$ean = filter_input(INPUT_POST, 'ean', FILTER_VALIDATE_INT);
Auf dem PC funktionierte das problemlos, nur auf dem Raspi lieferte die Funktion immer false zurück.
Auf die Spur des Problems brachten mich die Optionen des Filters, in denen man auch einen Min und Max Wert für die Festkommazahl setzen kann.
Der Raspi selbst ist zwar seit Version 3 auch 64-bittig, aber das System läuft noch immer mit 32 bit,wenn man nicht ausdrücklich das bis vor kurzen noch im Beta-Stadium befindliche 64bit-System auswählt. Und damit sind für Integer-Zahlen die Grenzen anders als bei meinem PC, der natürlich mit einem 64bit-Linux läuft.
PHP liefert selbst den Beweis mit den Konstanten PHP_INT_SIZE und PHP_INT_MAX. So sieht das bei einem 64bit-System aus:
$ php -r "echo PHP_INT_SIZE;"
8
$ php -r "echo PHP_INT_MAX;"
9223372036854775807
Und so beim 32-bittigen Raspi-System:
$ php -r "echo PHP_INT_SIZE;"
4
$ php -r "echo PHP_INT_MAX;"
2147483647
PHP_INT_SIZE liefert die Größe von Integer-Zahlen in Byte, also 4 Byte beim 32- und 8 Byte beim 64bit-System. PHP_INT_MAX gibt die größte darstellbare Integer-Zahl zurück, nämlich 9.223.372.036.854.775.807 (also knapp zehn Trillionen) bei 64bit und nur 2.147.483.647 oder gut zwei Milliarden bei 32 bit.
Da PHP keine Unsigned Integer kennt, fällt das Vozeichen-Bit weg und der theoretisch mit 32 bit darstellbare Ganzzahl-Wertebereich halbiert sich sogar nochmals um die Hälfte, nämlich von 4.294.967.295 (2³²-1) auf 2.147.483.647 (2³¹-1). Und das reicht für meine 13-stelligen EAN-Nummer eben nicht mehr aus.
Nachdem ich das erkannt hatte, war die Abhilfe relativ einfach: die EAN-Nummern müssen als String behandelt werden. Wird das Filter-Flag von FILTER_VALIDATE_INT auf FILTER_SANITIZE_SPECIAL_CHARS geändert, erscheint der Wert magischerweise auch auf dem Raspi.
Da ich mit den EAN-Nummer nicht rechnen will, macht das String-Format keine Probleme. Für die Validierung muss man sich aber eigene Gedanken machen, wenn man den String zum Beispiel in einem SQL-Befehl verwenden will (prepare ist Pflicht!).
Programmierer, die oft mit 8, 16 oder 32 bittigen SOCs zu tun haben, sind von diesen Einschränkungen wenig überrascht. Mich hat dieser Rückfall in die Computer-Steinzeit aber kalt erwischt und mich einige Stunden Lebenszeit gekostet.