PHP-Grundlagen Teil 2 – Typen in PHP verstehen

Welche Datentypen es in PHP gibt, wofür man sie wirklich braucht und warum strict_types von Anfang an gesetzt gehört – mit Übungsaufgaben zum Selbermachen.

PHP

PHP-Grundlagen Teil 2 – Typen in PHP verstehen

Marcel Strahl5 Min. Lesezeit

PHP-Grundlagen Teil 2 – Typen in PHP verstehen

Im ersten Teil ging es darum, warum PHP massiv unterschätzt wird.

Jetzt geht es richtig los. Und zwar da, wo jede Sprache anfängt: bei den Typen.

Egal was man später baut – APIs, Shops, Automatisierungen – am Ende schiebt man immer nur Daten durchs Programm. Und jedes Stück Daten hat einen Typ.

Wer Typen einmal wirklich verstanden hat, erspart sich später eine ganze Klasse an Bugs.


Was ist überhaupt ein Typ?

Ein Typ sagt PHP, was ein Wert ist und was man damit machen darf.

42 ist eine Zahl. Damit kann man rechnen. "42" ist Text, der nur zufällig aussieht wie eine Zahl.

Für uns Menschen sieht das fast gleich aus. Für das Programm ist das ein riesiger Unterschied.

Mit var_dump() kann man sich jederzeit anschauen, was ein Wert wirklich ist:

<?php
 
var_dump(42);      // int(42)
var_dump("42");    // string(2) "42"
var_dump(4.2);     // float(4.2)
var_dump(true);    // bool(true)

var_dump() wird beim Lernen dein wichtigstes Werkzeug. Unsicher? Reinschauen. Fertig.


Die skalaren Typen

Skalare Typen halten genau einen Wert. Davon hat PHP vier.

int – Ganzzahlen

<?php
 
$alter = 34;
$temperatur = -5;
$jahr = 2026;

Ganze Zahlen. Positiv oder negativ. Kein Komma, kein Text. Alles, was man zählen kann.

float – Kommazahlen

<?php
 
$preis = 19.99;
$pi = 3.14159;

Wichtig: Der Dezimaltrenner ist ein Punkt, kein Komma – auch wenn wir im Deutschen „Kommazahl“ sagen.

Floats haben außerdem eine fiese Falle eingebaut – dazu mehr im Zusatz am Ende des Artikels.

string – Text

<?php
 
$name = 'Marcel';
$begruessung = "Hallo $name"; // "Hallo Marcel"

Der Unterschied zwischen den Anführungszeichen:

  • 'Einfache Quotes' – der Text wird genau so genommen, wie er da steht
  • "Doppelte Quotes" – Variablen wie $name werden ersetzt (Interpolation)

Ich nehme standardmäßig einfache Quotes und doppelte nur dann, wenn ich Interpolation brauche. So sieht man auf den ersten Blick, wo etwas ersetzt wird und wo nicht.

bool – Wahr oder Falsch

<?php
 
$istAngemeldet = true;
$hatBezahlt = false;

Zwei mögliche Werte: true oder false. Mehr nicht.

Klingt banal, ist aber das Rückgrat jeder if-Abfrage – und damit von so ziemlich jedem Programm.


Die zusammengesetzten Typen

array – Listen und Maps

Das Schweizer Taschenmesser von PHP.

Ein Array kann eine Liste sein:

<?php
 
$sprachen = ['PHP', 'TypeScript', 'Go'];
 
echo $sprachen[0]; // PHP

Oder eine Map mit eigenen Schlüsseln (assoziatives Array):

<?php
 
$user = [
    'name'  => 'Marcel',
    'alter' => 34,
    'aktiv' => true,
];
 
echo $user['name']; // Marcel

In anderen Sprachen sind das zwei getrennte Typen – Liste und Dictionary/Map. In PHP macht beides das Array. Kann man drüber streiten, in der Praxis ist es vor allem eins: bequem.

object – Objekte

Instanzen von Klassen. Dazu kommt noch ein eigener Teil in dieser Serie, deshalb hier nur das Minimalbeispiel:

<?php
 
class User
{
    public function __construct(
        public string $name,
    ) {
    }
}
 
$user = new User('Marcel');
 
echo $user->name; // Marcel

Die Spezialfälle

null – Nichts

null bedeutet: Hier ist bewusst kein Wert.

<?php
 
$mittlererName = null; // hat halt nicht jeder

Nicht 0, nicht "", nicht false – sondern wirklich nichts.

Der Unterschied ist wichtiger, als er aussieht: 0 ist eine Antwort („null Euro Guthaben“). null ist keine Antwort („Guthaben unbekannt“).

Weitere Typen für später

Der Vollständigkeit halber – merken reicht, auswendig lernen muss das keiner:

  • callable – etwas, das man aufrufen kann (Funktionen, Closures)
  • iterable – etwas, worüber man mit foreach laufen kann
  • resource – Handles auf externe Dinge wie Dateien (Altlast, wird nach und nach ersetzt)
  • enum – feste Wertemengen, gibt es seit PHP 8.1 und ist großartig

Type Juggling – die Falle, die jeder kennt

Jetzt kommt der Teil, der PHP seinen schlechten Ruf eingebracht hat.

PHP ist von Haus aus locker mit Typen und wandelt automatisch um, wo es „passt“:

<?php
 
var_dump('5' + 3);     // int(8)  – String wird zur Zahl
var_dump('5' . 3);     // string(2) "53" – Zahl wird zum String
var_dump(0 == false);  // bool(true)
var_dump(0 === false); // bool(false)

Das nennt sich Type Juggling. Und das ist historisch der Grund für unzählige PHP-Bugs.

Deshalb zwei Regeln, die man sich ab Tag 1 angewöhnen sollte:

  1. Immer === statt == – der strikte Vergleich prüft Wert und Typ
  2. Immer declare(strict_types=1) am Anfang jeder Datei
<?php
 
declare(strict_types=1);
 
function addiere(int $a, int $b): int
{
    return $a + $b;
}
 
addiere(2, 3);     // int(5)
addiere('2', '3'); // TypeError – und das ist gut so

Ohne strict_types hätte PHP die Strings stillschweigend umgewandelt. Mit strict_types knallt es sofort – da, wo der Fehler entsteht. Und nicht drei Schichten später in der Datenbank.

Genau das will man.


Typen in Funktionen deklarieren

Modernes PHP kann Parameter- und Rückgabetypen deklarieren.

Und mein Rat dazu ist simpel: immer machen. Ausnahmslos.

<?php
 
declare(strict_types=1);
 
function berechnePreisMitSteuer(float $nettoPreis, float $steuersatz = 0.19): float
{
    return $nettoPreis * (1 + $steuersatz);
}
 
function findeBenutzername(int $id): ?string
{
    // ?string bedeutet: string ODER null
    return $id === 1 ? 'marcel' : null;
}

Das ? vor dem Typ macht ihn nullable – der Wert darf dann auch null sein. Seit PHP 8 gibt es außerdem Union Types wie int|string, aber die heben wir uns für später auf.

Was man dafür bekommt:

  • Der Code dokumentiert sich selbst
  • Die IDE kann einem wirklich helfen
  • Ganze Fehlerklassen verschwinden einfach

Kleiner Aufwand. Großer Effekt.


Aufgaben

Genug Theorie.

Am meisten hängen bleibt, wenn man es selbst tippt. Editor auf – oder für den Anfang reicht auch ein Online-PHP-Playground.

Aufgabe 1: Typen raten

Was gibt var_dump() hier jeweils aus? Erst überlegen, dann ausführen.

<?php
 
var_dump(10 / 3);
var_dump(10 / 2);
var_dump('10' + 5);
var_dump('abc' === 'abc');
var_dump(null == false);
var_dump(null === false);

Aufgabe 2: Steckbrief

Lege ein assoziatives Array $profil mit den Schlüsseln name (string), alter (int), hobbys (Array aus Strings) und beruf (string oder null) an. Gib danach einen Satz aus wie: Marcel ist 34 und hat 3 Hobbys.

Tipp: count() zählt Array-Einträge.

Aufgabe 3: Strict Types erleben

Schreibe eine Funktion verdopple(int $zahl): int. Rufe sie einmal ohne und einmal mit declare(strict_types=1) mit dem String '21' auf.

Was passiert jeweils – und warum?

Aufgabe 4: Der Geld-Klassiker

Ein Kunde kauft drei Artikel zu je 0.10 €. Prüfe mit ===, ob die Summe 0.30 ergibt. Falls nicht: Rechne dasselbe noch einmal in Cent als int und prüfe erneut.

Aufgabe 5: Typ-Detektiv

Schreibe eine Funktion beschreibeTyp(mixed $wert): string, die für einen beliebigen Wert einen Satz zurückgibt, z. B. "Das ist ein int mit dem Wert 42".

Tipp: get_debug_type() liefert den Typnamen als String.


Lösungsvorschläge

Erst selbst probieren. Ehrlich. Dann vergleichen.

Lösung zu Aufgabe 1
<?php
 
var_dump(10 / 3);        // float(3.3333333333333335) – Division ergibt float, wenn es nicht aufgeht
var_dump(10 / 2);        // int(5) – geht es auf, bleibt es int
var_dump('10' + 5);      // int(15) – Type Juggling wandelt den String um
var_dump('abc' === 'abc'); // bool(true)
var_dump(null == false); // bool(true)  – lockerer Vergleich
var_dump(null === false); // bool(false) – unterschiedliche Typen!
Lösung zu Aufgabe 2
<?php
 
declare(strict_types=1);
 
$profil = [
    'name'   => 'Marcel',
    'alter'  => 34,
    'hobbys' => ['Programmieren', 'Lesen', 'Gaming'],
    'beruf'  => 'Software-Entwickler',
];
 
echo sprintf(
    '%s ist %d und hat %d Hobbys.',
    $profil['name'],
    $profil['alter'],
    count($profil['hobbys']),
);
Lösung zu Aufgabe 3
<?php
 
declare(strict_types=1); // einmal mit, einmal ohne diese Zeile testen
 
function verdopple(int $zahl): int
{
    return $zahl * 2;
}
 
echo verdopple('21');
// ohne strict_types: 42 – PHP wandelt '21' still in 21 um
// mit strict_types:  TypeError – '21' ist ein String, kein int
Lösung zu Aufgabe 4
<?php
 
declare(strict_types=1);
 
$summe = 0.10 + 0.10 + 0.10;
var_dump($summe === 0.30); // bool(false) – Float-Rundungsfehler
 
$summeInCent = 10 + 10 + 10;
var_dump($summeInCent === 30); // bool(true) – deshalb Geld immer in Cent als int
Lösung zu Aufgabe 5
<?php
 
declare(strict_types=1);
 
function beschreibeTyp(mixed $wert): string
{
    return sprintf(
        'Das ist ein %s mit dem Wert %s',
        get_debug_type($wert),
        var_export($wert, true),
    );
}
 
echo beschreibeTyp(42);      // Das ist ein int mit dem Wert 42
echo beschreibeTyp('42');    // Das ist ein string mit dem Wert '42'
echo beschreibeTyp(true);    // Das ist ein bool mit dem Wert true
echo beschreibeTyp(null);    // Das ist ein null mit dem Wert NULL

Zusatz: Die Float-Falle

Und jetzt kommt eine Falle, in die wirklich jeder einmal reinläuft:

<?php
 
var_dump(0.1 + 0.2 === 0.3); // bool(false)

Ja, wirklich. false.

Floats sind intern binär gespeichert und dadurch nicht beliebig genau. Genau deshalb rechnet man in echten Projekten Geldbeträge niemals mit Floats, sondern in Cent als int.

Das ist keine Theorie. Das ist die Sorte Bug, die irgendwann in einer Rechnung landet.


Wie geht es weiter?

Das waren die Bausteine, aus denen jedes PHP-Programm besteht.

Im nächsten Teil geht es um Kontrollstrukturen – if, match, Schleifen. Also darum, wie ein Programm Entscheidungen trifft.

  • 5 Min. LesezeitC#

    C#-Grundlagen Teil 2 – Typen in C# verstehen

    Value Types, Reference Types, Nullable Reference Types und warum decimal für Geld gemacht ist: die Grundlagen des C#-Typsystems – mit Übungsaufgaben zum Selbermachen.

    • #C#
    • #Grundlagen
    • #Tutorial
    • #Software-Entwicklung
    • #Backend
  • 5 Min. LesezeitJava

    Java-Grundlagen Teil 2 – Typen in Java verstehen

    Primitives, Wrapper-Klassen, Autoboxing und die ==-Falle bei Strings: Was man über Javas Typsystem von Anfang an wissen sollte – mit Übungsaufgaben zum Selbermachen.

    • #Java
    • #Grundlagen
    • #Tutorial
    • #Software-Entwicklung
    • #Backend
  • 5 Min. LesezeitKotlin

    Kotlin-Grundlagen Teil 2 – Typen in Kotlin verstehen

    val vs. var, Typinferenz, Null-Safety und warum Kotlin nichts implizit umwandelt: die Grundlagen des Kotlin-Typsystems – mit Übungsaufgaben zum Selbermachen.

    • #Kotlin
    • #Grundlagen
    • #Tutorial
    • #Software-Entwicklung
    • #Backend