Tutorial · Mittel

PHP 8: Enums, Readonly Properties und Match

von André Heuer 28. Oktober 2025 12 Min. Lesezeit

PHP 8 hat den Alltag spürbar verändert – nicht durch ein einzelnes Mega-Feature, sondern durch eine Reihe von Sprachmitteln, die zusammen ein moderneres, robusteres PHP ergeben. Drei davon heben sich im Projektalltag besonders ab: Enums, readonly Properties und der match-Ausdruck. Dieses Tutorial zeigt, was sie leisten und wie du sie sofort einsetzt.

Enums: Ende der Klassenkonstanten-Wüste

Vor PHP 8.1 modellierte man feste Wertemengen über Klassenkonstantaten oder – schlimmer – über magische Strings. Enums machen daraus einen echten Typ: Der Compiler prüft mit, und die IDE weiß, welche Werte erlaubt sind.

php
<?php

enum Bestellstatus: string
{
    case Offen = 'offen';
    case Bezahlt = 'bezahlt';
    case Versendet = 'versendet';
    case Storniert = 'storniert';
}

// Typsicher statt String-Zauberei:
function versendeBestellung(Bestellstatus $status): void
{
    // ...
}

versendeBestellung(Bestellstatus::Versendet);   // ✓
versendeBestellung('versendet');                // ✗ TypeError

Enums können Methoden und Konstanten haben, Interfaces implementieren und sich – mit BackedEnum::tryFrom() – sicher aus externen Werten wie Datenbankeinträgen erzeugen lassen:

php
$status = Bestellstatus::tryFrom($dbWert);
if ($status === null) {
    throw new InvalidArgumentException("Unbekannter Status: {$dbWert}");
}

// Alle Fälle für Auswahllisten:
$optionen = Bestellstatus::cases();

Readonly Properties: Unveränderbarkeit als Vertrag

Value-Objects leben davon, dass sie nach der Erstellung nicht mehr verändert werden. Vor PHP 8.1 musste man das per Disziplin sicherstellen – mit readonly erledigt es die Sprache selbst.

php
<?php

final class Geld
{
    public function __construct(
        public readonly int $cent,
        public readonly string $waehrung = 'EUR',
    ) {}
}

$preis = new Geld(1999);
echo $preis->cent;        // 1999

$preis->cent = 2500;      // ✗ Error: Cannot modify readonly property
Tipp: Readonly + Promotion

Constructor Property Promotion und readonly ergänzen sich perfekt: Value-Objects in drei Zeilen, die der Compiler gegen versehentliche Mutation schützt.

Match: Bedingte Logik ohne Boilerplate

Der match-Ausdruck ersetzt viele switch-Konstrukte: Er ist ein Ausdruck (liefert also einen Wert), vergibt streng (===) und erzwingt Vollständigkeit, wenn du ihn ohne default nutzt.

php
// Vorher: switch mit temporärer Variable
$label = '';
switch ($status) {
    case Bestellstatus::Offen:
        $label = 'Noch offen';
        break;
    case Bestellstatus::Versendet:
        $label = 'Unterwegs';
        break;
    default:
        $label = 'Unbekannt';
}

// Nachher: match als Ausdruck
$label = match ($status) {
    Bestellstatus::Offen     => 'Noch offen',
    Bestellstatus::Versendet => 'Unterwegs',
    default                  => 'Unbekannt',
};

// Mehrere Werte pro Arm:
$istFinal = match (true) {
    $status === Bestellstatus::Versendet,
    $status === Bestellstatus::Storniert => true,
    default => false,
};
Achtung: match ohne default

Lässt du default weg und kein Arm passt, wirft PHP eine UnhandledMatchError-Exception. Das ist ein Feature: Es macht vergessene Fälle sichtbar statt stillschweigend durchzureichen.

Alle drei zusammen: ein Beispiel

Enums, readonly und match entfalten ihren Nutzen erst im Zusammenspiel. Ein kleiner Service, der alle drei nutzt:

php
<?php

final class VersandService
{
    public function labelFuer(Bestellstatus $status): string
    {
        return match ($status) {
            Bestellstatus::Offen     => 'Warten auf Zahlung',
            Bestellstatus::Bezahlt   => 'In Vorbereitung',
            Bestellstatus::Versendet => 'Paket ist unterwegs',
            Bestellstatus::Storniert => 'Storniert',
        };
    }
}

Kein String-Raten, keine versehentliche Mutation, keine vergessenen switch-Fälle – und die IDE autocomplete-freundlich durchgehend.

Fazit

Enums geben Wertemengen einen Typ, readonly macht Unveränderbarkeit durchsetzbar und match ersetzt fehleranfällige switch-Blöcke durch prägnante Ausdrücke. Wer diese drei Sprachmittel konsequent nutzt, schreibt PHP, das weniger Bugs hat und sich fast wie statisch getypt anfühlt – ohne den Umweg über eine Transpilation.

Das könnte dich auch interessieren

Tutorial

JavaScript: async/await richtig verstehen

async/await sieht wie synchroner Code aus, ist es aber nicht. Wir erklären die Ereignisschleife, häufige Stolperfallen wie ungehandelte Promise-Ablehnungen und parallele Abläufe mit Promise.all.

Weiterlesen