declare(strict_types=1) – wenn "5" keine 5 mehr sein soll
PHP wandelt Typen bei Bedarf still um – aus dem String "5" wird eine 5, aus "12 Stück" auch. Eine Zeile am Dateianfang beendet das Raten und macht aus einem stillen Rechenfehler eine laute Ausnahme.
PHP ist von Haus aus nachsichtig. Eine Funktion, die ein int erwartet, nimmt auch "5", 5.0 oder true – und rechnet damit weiter. Das ist bequem, bis es das nicht mehr ist:
function rabatt(int $prozent): int { return $prozent; }
rabatt("10"); // 10 – ok, gemeint war's
rabatt(10.9); // 10 – abgeschnitten, ohne Hinweis
rabatt(true); // 1 – ??Ein Feld aus einem Formular kommt immer als String. Ist es leer, wird daraus eine 0, und der Rabatt verschwindet still.
Die eine Zeile
<?php
declare(strict_types=1);Sie muss die allererste Anweisung der Datei sein – vor jedem namespace, vor jedem require, und es darf kein Leerzeichen vor dem <?php stehen.
Ab da werden Typen nicht mehr umgedeutet:
rabatt("10"); // TypeError: Argument #1 ($prozent) must be of type int, string given
rabatt(10.9); // TypeError
rabatt(10); // 10Die einzige Ausnahme, die auch streng erlaubt bleibt: int darf zu float erweitert werden (rabatt(10) in einer Funktion mit float $x geht), weil dabei nichts verloren geht.
Wo die Konvertierung stattdessen hingehört
Streng zu sein heißt nicht, überall zu casten – sondern die Umwandlung an die Grenze zu legen: dort, wo fremde Daten hereinkommen.
declare(strict_types=1);
// Grenze: Eingaben aus dem Request prüfen und typisieren
$prozent = filter_input(INPUT_POST, 'prozent', FILTER_VALIDATE_INT);
if ($prozent === false || $prozent === null) {
throw new InvalidArgumentException('Prozentwert fehlt oder ist keine Zahl.');
}
// Innen: alles hat den richtigen Typ, niemand rät mehr
$preis = rabatt($prozent);Damit passiert der Fehler dort, wo man ihn versteht – bei der Eingabe – statt drei Ebenen tiefer in einer Berechnung.
Zwei Dinge, die oft überraschen
- Die Regel gilt je Datei, und zwar für die Aufrufe, die in dieser Datei stehen. Eine strenge Datei, die eine Bibliothek ohne
strict_typesaufruft, prüft trotzdem streng; umgekehrt nicht. Deshalb: in jede eigene Datei schreiben, nicht nur in die Einstiegsdatei. - Rückgabewerte sind mit betroffen. Eine Funktion mit
: int, die"12"zurückgibt, wirft im strengen Modus ebenfalls einenTypeError.
Fallstrick
Wenn du strict_types nachträglich in ein gewachsenes Projekt einbaust, fang bei neuen Dateien an und arbeite dich nach vorn – Datei für Datei, mit Tests dazwischen. Und rechne mit einem Klassiker: json_decode liefert Zahlen aus JSON je nach Quelle als int oder float, und eine ID aus der Datenbank kommt über PDO als String, solange du sie nicht castest. Genau diese Stellen sind es, die der strenge Modus aufdeckt – das ist der Sinn der Übung, nicht ihr Ärgernis.
Ich schreibe PHP, das im Zweifel laut wird statt still falsch zu rechnen. Wenn du ein Backend brauchst, das man in zwei Jahren noch anfassen kann: bymw.de.
Quellen
Du brauchst mehr als ein Snippet?
Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.
Projekt anfragen →Verwandte Snippets
Beträge und Zahlen in PHP formatieren – number_format, sprintf und Intl
1234.5 ist keine Anzeige, sondern ein Wert. Auf der Rechnung soll 1.234,50 € stehen, in der API 1234.50 und im Dateinamen 1234-50. Drei Aufgaben, drei Werkzeuge – und ein Fehler, den fast jeder einmal macht.
Benannte Argumente in PHP 8 – Schluss mit true, false, null, true
Ein Aufruf wie erstelle($a, true, false, null, true) sagt nichts darüber, was die Wahrheitswerte bedeuten. Mit benannten Argumenten steht es im Aufruf – und optionale Parameter lassen sich überspringen.
Reguläre Ausdrücke in PHP – benannte Gruppen statt $m[3]
Ein Treffer-Array aus Zahlen liest sich nach zwei Wochen wie eine Geheimschrift. Benannte Gruppen geben jedem Teil einen Namen – und preg_replace_callback ersetzt damit Dinge, die kein einfacher Ersetzungsstring kann.