# Das Typsystem von PHP

> Das PHP-Typsystem erklärt: Datentypen, Typdeklarationen von PHP 7.1 bis 8.3, strict_types und lose Vergleiche, mit Beispielen und Bezug zur Sicherheit.

Quelle: https://phpsos.de/php/typsystem/  
Stand: 25.10.2026  
Anbieter: PHP SOS, PHP-Notfallhilfe und Server-Sicherheit. Soforthilfe per WhatsApp: https://wa.me/491736494914?text=Hallo%20PHP%20SOS%2C%20wir%20brauchen%20Hilfe%20mit%20unserem%20PHP-Server.%20Firma%3A%20%E2%80%A6%20Website%3A%20%E2%80%A6

**Kurz gesagt:** PHP ist dynamisch typisiert: Der Typ eines Werts steht erst zur Laufzeit fest, und ohne weitere Vorgaben wandelt PHP Werte bei Bedarf automatisch um. Seit PHP 7 lassen sich Parameter, Rückgaben und Eigenschaften aber mit Typen versehen, und `declare(strict_types=1)` macht die Prüfung streng. Wer die Regeln kennt und strikte Vergleiche mit `===` nutzt, vermeidet eine ganze Klasse von Logik- und Sicherheitsfehlern.

## Dynamisch typisiert, aber nicht typlos

In PHP muss man bei `$preis = 19.90;` keinen Typ angeben. PHP erkennt, dass es sich um eine Gleitkommazahl handelt. Wird der Wert später mit einer Zeichenkette verknüpft, wandelt PHP ihn um. Dieses Verhalten nennt man Type Juggling, also automatische Typumwandlung. Es macht den Einstieg leicht, kann aber zu überraschenden Ergebnissen führen.

Für Entscheider ist das relevant, weil viele ältere PHP-Anwendungen ohne Typangaben geschrieben wurden. Solcher Code ist schwerer zu prüfen und zu modernisieren. Neuere Projekte nutzen Typen konsequent, was Fehler früher sichtbar macht und die [statische Analyse](https://phpsos.de/php/statische-analyse/) mit Werkzeugen wie PHPStan oder Psalm erst richtig wirksam werden lässt.

## Die Typen von PHP im Überblick

Das PHP-Handbuch nennt neun interne Typen, die jeder Ausdruck haben kann. Üblicherweise werden sie in drei Gruppen eingeteilt:

| Gruppe | Typen | Beispiel |
|---|---|---|
| Skalare Typen | `bool`, `int`, `float`, `string` | `true`, `42`, `3.5`, `"Text"` |
| Zusammengesetzte Typen | `array`, `object`, `callable` | `[1, 2]`, `new DateTime()` |
| Besondere Typen | `null`, `resource` | `null`, eine geöffnete Datei |

Für Typprüfungen empfiehlt das Handbuch die `is_*()`-Funktionen wie `is_int()`. Zum Untersuchen eignet sich `get_debug_type()`, das seit PHP 8.0.0 die gebräuchlichen Typnamen liefert, während das ältere `gettype()` zum Beispiel `"integer"` und `"double"` zurückgibt.

Neben der automatischen Umwandlung gibt es die ausdrückliche: Mit einem Cast wie `(int) $wert` oder mit `settype()` legt der Code selbst fest, welchen Typ ein Wert haben soll. Das ist bei Eingaben aus Formularen üblich, denn alles, was über `$_GET` oder `$_POST` hereinkommt, ist zunächst eine Zeichenkette oder ein Array. Ein Cast prüft aber nicht, ob der Wert sinnvoll war: Aus `"abc"` wird stillschweigend `0`. Für Eingaben ist eine echte Prüfung mit `filter_var()` deshalb meist die bessere Wahl.

Klassen und Interfaces sind in PHP ebenfalls Typen. Eine Funktion kann also verlangen, dass ein Parameter ein Objekt einer bestimmten Klasse ist oder ein bestimmtes Interface erfüllt. Wie Klassen, Interfaces und Enums zusammenspielen, erklärt die Seite [Objektorientierung in PHP](https://phpsos.de/php/objektorientierung/).

## Typdeklarationen: von PHP 7.1 bis 8.3

Typdeklarationen legen fest, welche Werte eine Funktion annimmt und zurückgibt. Das Typsystem ist über viele Versionen gewachsen. Laut Änderungsprotokoll des Handbuchs kamen unter anderem diese Möglichkeiten hinzu:

| Version | Neu |
|---|---|
| 7.1.0 | nullable Typen (`?int`), `void`, `iterable` |
| 7.2.0 | `object` |
| 7.4.0 | typisierte Klasseneigenschaften |
| 8.0.0 | Union-Typen (mehrere erlaubte Typen in einer Angabe), `mixed`, Rückgabetyp `static` |
| 8.1.0 | Intersection-Typen (`A&B`), Rückgabetyp `never` |
| 8.2.0 | DNF-Typen, Literaltyp `true`, `null` und `false` als eigenständige Typen |
| 8.3.0 | typisierte Klassen-, Interface-, Trait- und Enum-Konstanten |

DNF steht für disjunktive Normalform und erlaubt Kombinationen wie `(A&B)|null`. Wer PHP-Versionen plant, sieht an dieser Tabelle auch, welche Sprachmittel eine Anwendung voraussetzt.

## strict_types: Umwandlung oder TypeError

Ohne weitere Angabe arbeitet PHP im umwandelnden Modus. Eine Funktion mit `int`-Parametern nimmt dann auch `1.5` an und macht daraus `1`; seit PHP 8.1 ist diese verlustbehaftete Umwandlung als veraltet markiert. Mit `declare(strict_types=1)` am Dateianfang wirft PHP stattdessen einen `TypeError`.

```php
<?php
declare(strict_types=1);

function summe(int $a, int $b): int
{
    return $a + $b;
}

echo summe(1, 2);      // 3
echo summe(1.5, 2.5);  // TypeError, statt stillschweigend 3
```

Zwei Feinheiten sind wichtig. Erstens gilt `strict_types` für Aufrufe aus der Datei, in der es steht, nicht für die dort definierten Funktionen. Ruft eine Datei ohne `strict_types` dieselbe Funktion auf, wird umgewandelt. Zweitens ist eine Ganzzahl dort, wo eine Gleitkommazahl erwartet wird, auch im strengen Modus erlaubt.

## Lose und strikte Vergleiche

Der Operator `==` vergleicht nach Typumwandlung, `===` vergleicht Wert und Typ ohne Umwandlung. Das Handbuch empfiehlt in den meisten Fällen `===` und `!==`, weil die Umwandlungsregeln nicht immer offensichtlich sind.

```php
<?php
var_dump(0 == "a");    // PHP 7: true,  PHP 8: false
var_dump("1" == "01"); // true, beide sind numerische Zeichenketten
var_dump("1" === "01");// false, gleicher Typ, aber andere Zeichenkette
var_dump(1 == true);   // true
var_dump(1 === true);  // false
```

Mit PHP 8.0 wurden Vergleiche zwischen Zahlen und nicht-numerischen Zeichenketten vernünftiger. Ältere Anwendungen können sich durch das Upgrade anders verhalten, etwa in `switch`-Blöcken. Der ebenfalls mit PHP 8.0 eingeführte `match`-Ausdruck vergleicht immer strikt. Wie lose Vergleiche zu Sicherheitslücken führen, zum Beispiel bei Token- oder Passwortprüfungen, beschreibt der Beitrag [Type Juggling: lose Vergleiche als Sicherheitsrisiko](https://phpsos.de/blog/type-juggling-php/).

## Typen, Upgrades und PHP2Shell

Ein strenges Typsystem macht Anwendungscode robuster, aber es schützt nicht vor Fehlern im Interpreter selbst. Die PHP2Shell-Lücken CVE-2026-109618 und CVE-2026-109619 liegen in der Speicher- und Anfrageverwaltung von PHP. Behoben sind sie in PHP 8.5.12, 8.4.27, 8.3.36 und 8.2.35; danach müssen alle PHP-Prozesse neu starten.

Das Typsystem spielt trotzdem eine Rolle, und zwar beim Upgrade. Anwendungen, die noch auf PHP 8.1 oder älter festhängen, erhalten vom PHP-Projekt keine offiziellen Updates mehr. Gut typisierter Code lässt sich deutlich leichter auf eine unterstützte Version heben, weil Werkzeuge Unverträglichkeiten früh finden. Bei älteren Projekten unterstützt unsere [Migration auf eine unterstützte PHP-Version](https://phpsos.de/leistungen/php-migration-legacy/).

> **Tipp:**
> Aktivieren Sie `strict_types` schrittweise in neuen und überarbeiteten Dateien. So wächst die Typsicherheit, ohne dass alter Code auf einen Schlag bricht.

## Wie hilft PHP SOS konkret?

- Wir prüfen, welche PHP-Version Ihre Anwendung mindestens braucht, und gleichen das mit den behobenen Versionen ab.
- Wir lassen statische Analyse über den Code laufen und markieren Stellen mit losen Vergleichen in sicherheitsrelevanten Prüfungen.
- Wir planen Upgrades so, dass geänderte Vergleichsregeln vorher getestet werden.
- Wir spielen das PHP-Update ein, starten alle Worker neu und dokumentieren den Stand.


## Häufige Fragen

**Ist PHP stark oder schwach typisiert?**  
PHP ist dynamisch typisiert: Der Typ einer Variablen steht erst zur Laufzeit fest. Ohne strict_types wandelt PHP Werte bei Bedarf um. Mit Typdeklarationen und strict_types lässt sich der Code aber sehr streng machen.

**Was bewirkt declare(strict_types=1)?**  
Es schaltet für Aufrufe aus der jeweiligen Datei die automatische Umwandlung skalarer Werte ab. Passt ein Wert nicht zum deklarierten Typ, wirft PHP einen TypeError. Einzige Ausnahme ist eine Ganzzahl, wo eine Gleitkommazahl erwartet wird.

**Warum ist 0 == "a" in PHP 8 falsch, in PHP 7 aber wahr?**  
Bis PHP 7 wurde eine nicht-numerische Zeichenkette beim Vergleich mit einer Zahl in eine Zahl umgewandelt, aus "a" wurde 0. Seit PHP 8.0 vergleicht PHP in diesem Fall nicht mehr numerisch, das Ergebnis ist false.

**Schützen Typen vor Sicherheitslücken in PHP selbst?**  
Nein. Typen verhindern Fehler in Ihrem Anwendungscode. Lücken im Interpreter wie PHP2Shell werden nur durch ein PHP-Update geschlossen. Moderne Typfunktionen setzen aber aktuelle PHP-Versionen voraus und sind damit ein guter Anlass zum Upgrade.

## Quellen

- [PHP-Handbuch: Typdeklarationen](https://www.php.net/manual/de/language.types.declarations.php)
- [PHP-Handbuch: Einführung in Typen](https://www.php.net/manual/de/language.types.intro.php)
- [PHP-Handbuch: Vergleichsoperatoren](https://www.php.net/manual/de/language.operators.comparison.php)
- [PHP 8.0 Release](https://www.php.net/releases/8.0/en.php)
