PHP Problem

PHP:
$vorname = $_POST['vorname'];

sowas gehört seit PHP 5.2 der Vergangenheit an.

Besser:
PHP:
$vorname = filter_input(INPUT_POST, 'vorname');

selbiges auch bei $_GET

http://php.net/manual/de/function.filter-input.php

Ich widerspreche nicht grundsätzlich, aber es gibt mit filter_input meines Erachtens mindestens drei Probleme:

- Erstens: Das gesamte Filterkram ist aus einem mir schleierhaften Grund noch immer miserabel dokumentiert. Ich kann mit so was wenig bis gar nichts anfangen. Was tut zum Beispiel ein FILTER_FLAG_STRIP_LOW oder ein FILTER_FLAG_STRIP_HIGH? Bedeutet etwa „[r]emove all characters except digits, plus and minus sign“, dass eine Eingabe wie "+3-4" oder "++4" zulässig ist? Wahrscheinlich „nein“, aber so, wie es in der Doku steht, bedeutet es „ja“. (De facto übrigens auch. Ich habe keinen Schimmer, wozu FILTER_SANITIZE_NUMBER_INT gut sein soll. "+3-4" ist definitiv kein Integer.) Programmierung ist ein Gebiet, das Exaktheit verlangt. Anders funktioniert es nicht. Ich sehe daher keine Chance, diese Filter sinnvoll zu verwenden, wenn nicht glasklar definiert ist, was sie tun. Das Fehlen einer Dokumentation zeigt für mich einerseits, dass die Entwickler eine schluderige Einstellung zum Thema haben, und andererseits sind undefinierte Dinge nun mal leider undefiniert. Selbst dann, wenn ich durch Ausprobieren oder Lesen des C-Codes in Erfahrung bringen würde, was die Filter genau tun, wäre das keine wirkliche Gewissheit, sondern mehr ein Implementationsdetail, auf dessen gegenwärtigen Zustand ich mich verlasse, das sich aber theoretisch verändern könnte (wie etwa die Sortierreihenfolge von usort bei gleichen Einträgen). Das ist viel zu viel Ungewissheit.

- Zweitens: Konstrukte wie filter_input(INPUT_GET, …) sind meines Erachtens nur sehr umständlich zu testen. PHP bezieht die Daten in dem Fall von einer globalen Stelle, die nicht mit den superglobalen Variablen ($_GET, $_POST, …) synchronisiert ist.

PHP:
$_GET['foo'] = 'bar';
var_dump(filter_input(INPUT_GET, 'foo')); // NULL

Ich habe keine Ahnung, wie man damit Request-Daten sinnvoll für Tests mocken könnte. Zudem ist filter_input genauso ein Zugriff auf eine globale Stelle wie $_GET oder $_POST. Die Nachteile sind die gleichen. Worin liegt der Vorteil von filter_input? Hier ein Beispiel aus einem verbreiteten Framework für eine Abstraktion von Requests, die meines Erachtens insgesamt mehr Sinn ergibt. (Die gesamte Klasse/Komponente.)

- Drittens: Welches Problem lösen die Filter? Für Validierung/Sanitization im Sinne der Geschäftslogik sind sie zu generisch (und zu unklar definiert). Oder anders gesagt: Die Filter-Komponente ist schlecht konzipiert und positioniert. Es ist unklar, worin ihr Zweck besteht. Es gibt meines Wissens beispielsweise keinen Filter, der sicherstellt, dass ein Request-Parameter-Inhalt in UTF-8 NFC vorliegt, der also die von der Anwendung erwartete Kodierung eines Strings sicherstellt. Außerdem immer die generelle Frage, ob man will, dass eine Eingabe wie "foo10bar" als int(10) (oder so was in der Art) interpretiert wird?

PHP:
var_dump(
    filter_var('foo+bar10', FILTER_SANITIZE_NUMBER_INT) // string(3) "+10"
);

Das ist mit Sicherheit nicht das, was beabsichtigt ist, und trägt eher dazu bei, Bugs zu verschleiern, weil PHP die Eingaben eben doch noch irgendwie als gültig erkennt, obwohl sie es eigentlich nicht ist.
 
Zuletzt bearbeitet:
Ja. Don’t get me started… (Wobei manche Doku auch ganz okay ist.) Fehlende oder unzureichende Doku ist tendenziell besonders bei neueren Funktionen und in den Sprachkern integrierten Klassen ein wesentliches Problem (etwa vielfach bei SPL, das eigentlich ganz nette Dinge enthält – vielleicht ;)). Ich weiß nicht, was Leute sich dabei denken, den nötigen C-Code für die Funktionen und Klassen zu schreiben, sie dann aber nicht so zu dokumentieren, dass Nutzer sie ohne größere Umstände einsetzen können.

Das letzte Beispiel einer irgendwie schon größeren Doku-Leerstelle war für mich das hier: https://www.php.de/forum/webentwicklung/php-einsteiger/1477792-tage-in-monate-wochen-tage-berechnen (DateTime::diff rechnet vor der Berechnung in UTC/GMT um, was mitunter zu „seltsamen“ Resultaten führt, wenn man eigentlich in anderen Zeitzonen operiert. Keinen Plan, woher man das wissen soll. In der Doku steht es nicht.)
 
Zuletzt bearbeitet:
Grundsätzlich bin ich bei fast allen von Dir genannten Punkten Deiner Meinung.

Allerdings gibt es auch einen Punkt, bei dem ich vorerst in Widerspruch gehen muss.

var_dump(
filter_var('foo+bar10', FILTER_SANITIZE_NUMBER_INT) // string(3) "+10"
);
ist wie der Name schon sagt, ein "Sanitize"-Filter - Diese Säubert/Bereinigt also einen Eingabewert. Es erscheint mir also nur logisch, dass alle Zeichen, welche nicht in das Schema passen entfernt werden.

Etwas wie
PHP:
filter_input(INPUT_POST,'email',FILTER_VALIDATE_EMAIL);
würde, wenn der Eingabewert keine valide E-Mail-Adresse ist "false" als Rückgabewert liefern und somit als vollwertige Validierung dienen.

Liebe Grüße
 
Ja, da ist was dran. Gibt ja auch so Geschichten wie den Robustheitsgrundsatz. Irgendwie bin ich trotzdem kein Fan davon, Eingaben wie "foo10bar20" dann am Ende als int(1020) anzusehen (nach Sanitization und Validation). (Da wäre es wohl geschickter, die Sanitization zu „überspringen“.)

Edit: Also, mir geht es mit dem vorherigen Absatz darum, noch mal so ein wenig den „Zweck“ oder die Umsetzung dieses Sanitization-Filters (bzw. mancher Filter) zu hinterfragen. Dass die Kritik in meinem vorherigen Post nicht in dem Maße auf die Validation-Filter zutrifft, ist ein berechtigter Einwand. Ich hatte die verschiedenen Zuständigkeiten (Sanitization und Validation) heute morgen zu sehr vermischt.
 
Zuletzt bearbeitet:
Zurück