Standardmäßig haben Enum-Fälle keine skalare Entsprechung. Es handelt sich einfach um Singleton-Objekte. In vielen Fällen ist es jedoch auch notwendig, einen Enum-Fall von einer Datenbank oder einem ähnlichen Datenspeicher zu lesen und in diese zu schreiben, sodass es sinnvoll ist, ein intern definiertes skalares (und damit einfach serialisierbares) Äquivalent zu haben.
Um für eine Aufzählung eine skalare Entsprechung zu definieren, wird folgende Syntax verwendet:
<?php
enum Suit: string
{
case Hearts = 'H';
case Diamonds = 'D';
case Clubs = 'C';
case Spades = 'S';
}
?>
Ein Fall, der eine skalare Entsprechung hat, wird als "Backed Case" bezeichnet, da er durch einen einfacheren Wert "unterstützt" wird. Eine Enum, die ausschließlich Backed Cases enthält, wird als "Backed Enum" bezeichnet. Eine Backed Enum kann nur Backed Cases enthalten. Eine Pure Enum kann nur Pure Cases enthalten.
Eine Backed Enum kann entweder durch den Typ int
oder
den Typ string
unterstützt werden, wobei eine gegebene
Aufzählung jeweils nur einen einzigen Typ unterstützt (d. h. der
Vereinigungstyp int|string
wird nicht unterstützt). Wenn
eine Aufzählung als "skalar äquivalent" gekennzeichnet ist, müssen alle
Fälle eine eindeutige, explizit definierte skalare Entsprechung haben. Es
gibt keine automatisch generierten skalare Entsprechungen (z. B.
fortlaufende Ganzzahlen). Backed Cases müssen eindeutig sein; zwei Backed
Enum Cases dürfen nicht dieselbe skalare Entsprechung haben. Eine Konstante
kann jedoch auf einen Fall verweisen und somit einen Alias erzeugen. Siehe
Aufzählungskonstanten.
Die Entsprechungen müssen Literale sein oder literale Ausdrücke. Konstanten
und Ausdrücke mit Konstanten werden nicht unterstützt. Das heißt,
1 + 1
ist erlaubt, aber
1 + SOME_CONST
ist nicht erlaubt.
Backed Cases haben eine zusätzliche schreibgeschützte Eigenschaft,
value
, die der in der Definition angegebene Wert ist.
<?php
print Suit::Clubs->value;
// Gibt "C" aus
?>
Um sicherzustellen, dass die Eigenschaft value
schreibgeschützt ist, kann eine Variable nicht als Referenz zugewiesen
werden. Das bedeutet, dass Folgendes einen Fehler auslöst:
<?php
$suit = Suit::Clubs;
$ref = &$suit->value;
// Error: Cannot acquire reference to property Suit::$value
?>
Backed Enums implementieren die interne Schnittstelle BackedEnum, die zwei zusätzliche Methoden zur Verfügung stellt:
from(int|string): self
akzeptiert einen skalaren Wert
und gibt den entsprechenden Enum-Fall zurück. Wird ein solcher nicht
gefunden, löst das einen ValueError aus. Dies ist
vor allem in Fällen nützlich, in denen der eingegebene Wert
vertrauenswürdig ist und ein fehlender Enum-Wert als Fehler angesehen
werden sollte, der die Anwendung abbricht.
tryFrom(int|string): ?self
akzeptiert einen skalaren
Wert und gibt den entsprechenden Enum-Fall zurück. Wenn keiner gefunden
wird, wird null
zurückgegeben. Dies ist vor allem in
Fällen nützlich, in denen der eingegebene Wert nicht vertrauenswürdig ist
und der Aufrufer seine eigene Fehlerbehandlung oder Logik für
Standardwerte implementieren möchte.
Die Methoden from()
und tryFrom()
folgen den Standardregeln für schwache bzw. starke Typisierung. Bei
schwacher Typisierung ist die Übergabe einer Ganzzahl oder einer
Zeichenkette zulässig und das System wandelt den Wert entsprechend um. Auch
Gleitkommazahlen können übergeben werden und werden dann entsprechend
umgewandelt. Im Modus der strengen Typisierung führt die Übergabe einer
Ganzzahl an from()
bei einer Enum mit Zeichenketten
(oder umgekehrt) zu einem TypeError. Für
Gleitkommazahlen gelten in allen Fällen die gleichen Typisierungsregeln.
Bei allen anderen Typen wird in beiden Modi ein TypeError ausgelöst.
<?php
$record = get_stuff_from_database($id);
print $record['suit'];
$suit = Suit::from($record['suit']);
// Ungültige Daten führen zu einem ValueError:
// "X" is not a valid scalar value for enum "Suit"
print $suit->value;
$suit = Suit::tryFrom('A') ?? Suit::Spades;
// Ungültige Daten ergeben null, also wird stattdessen Suit::Spades verwendet.
print $suit->value;
?>
Die manuelle Definition der Methoden cases()
oder
tryFrom()
führt bei einer Enum zu einem fatalen Fehler.