MWCodebymw.de ↗
PHP

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);     // 10

Die 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_types aufruft, 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 einen TypeError.

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

#PHP#Typen#strict_types#Qualität#Fehlersuche

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 →