Neu in PHP 8.1: enums – ein konkretes Beispiel

Mit PHP 8.1 haben endlich Enumerations Einzug in die Sprache gehalten, kurz enums. Nachfolgend ein Beispiel, wie enum konkret verwendet werden kann.

Vor PHP 8.1 musste man für ein ähnliches Verhalten auf Klassenvariablen zurückgreifen:

class Status
{
    public const IDLE = 1;
    public const RUNNING = 2;
    public const ERROR = 3;
}

Warum sollte man das tun? Folgendes Beispiel verdeutlicht dies. Angenommen wir haben einen Task. Welche Status gibt es neben idle? Ist idle überhaupt ein valider Status?

Task::create([
    'title' => 'My special task',
    'status' => 'idle'
]);

Hier könnte die oben beschriebene Kasse helfen:

Task::create([
    'title' => 'My special task',
    'status' => Status::IDLE
]);

Wechsel zu enum

Nun zum enum. Aus der Status-Klasse wird:

enum Status: int
{
    case IDLE = 1;
    case RUNNING = 2;
    case ERROR = 3;
}

Und unseren Task können wir wie folgt erstellen:

Task::create([
    'title' => 'My special task',
    'status' => Status::IDLE->value
]);

In der Datenbank wird nun als Status der Wert von IDLE hinterlegt, also 1. Aber wie bekommen wir nun IDLE zurück, wenn wir nur die 1 haben? Ein Code-Beispiel:

$task = Task::find(23);

$status = Status::from($task->status);

Auf diese Weise erhalten wir ein Enum-Objekt zurück. Worin liegt hier der Vorteil?

Zusätzliche Methoden

Enums können Methoden enthalten, so dass wir beispielsweise eine Methode die Ausgabe des leserlichen Status implementieren können:

enum Status: int
{
    case IDLE = 1;
    case RUNNING = 2;
    case ERROR = 3;

    public function readable(): string
    {
        return match ($this) {
            self::IDLE => 'is idle',
            self::RUNNING => 'is running',
            self::ERROR => 'an error occurred',
        };
    }
}

Nun können wir den obigen Aufruf ergänzen:

$status = Status::from($task->status)->readable();

… und erhalten in diesem Fall is idle zurück.

Mögliche Werte

Um alle gültigen Status auszugeben kann man auf folgenden Code zurückgreifen (das Beispiel nutzt Laravel Blade):

<select name="status">
    @foreach(Status::cases() as $status)
        <option value="{{ $status->value }}">
            {{ $status->readable() }}
        </option>
    @endforeach
</select>

Schreibe einen Kommentar