A backed enum gives every case a scalar value, an int or a string. That makes it possible to store the enum in a database, a form or a JSON API, and to turn the stored value back into a case.
<?php
enum Status: string
{
case Draft = "draft";
case Published = "published";
case Archived = "archived";
}
echo Status::Published->value . "\n";
echo Status::Published->name;
published
Published
: stringafter the enum name makes it “string-backed”. Use: intfor numbers.- Every case needs a value, and values must be unique.
->valueis the stored value,->nameis the case name.
From a value to a case: from() and tryFrom()
<?php
enum Status: string
{
case Draft = "draft";
case Published = "published";
}
$a = Status::from("published");
$b = Status::tryFrom("deleted");
echo $a->name . "\n";
var_dump($b);
try {
Status::from("deleted");
} catch (ValueError $e) {
echo $e->getMessage();
}
Published
NULL
"deleted" is not a valid backing value for enum Status
from()throws aValueErrorif the value does not exist.tryFrom()returnsnullinstead.
Validating input
tryFrom() is perfect for validating form or URL input against the allowed options.
<?php
enum Sort: string
{
case Newest = "newest";
case Price = "price";
case Name = "name";
}
$input = "price; DROP TABLE users"; // imagine this came from the URL
$sort = Sort::tryFrom($input) ?? Sort::Newest;
echo $sort->value;
newest
Only real cases get through. Everything else falls back to the default.
Save to and load from a database
<?php
enum Role: string
{
case Admin = "admin";
case Editor = "editor";
}
class User
{
public function __construct(public string $name, public Role $role) {}
}
// Saving: store the value
$user = new User("Ana", Role::Editor);
$stored = $user->role->value;
echo "Stored: $stored\n";
// Loading: turn the value back into a case
$loaded = new User("Ana", Role::from($stored));
echo "Loaded: " . $loaded->role->name;
Stored: editor
Loaded: Editor
Build a select list
<?php
enum Country: string
{
case India = "IN";
case Nepal = "NP";
public function label(): string
{
return ucfirst(strtolower($this->name));
}
}
foreach (Country::cases() as $case) {
echo "<option value=\"{$case->value}\">{$case->label()}</option>\n";
}
<option value="IN">India</option>
<option value="NP">Nepal</option>
JSON
A backed enum converts to its value in json_encode().
<?php
enum Status: string
{
case Draft = "draft";
}
echo json_encode(["status" => Status::Draft]);
{"status":"draft"}
Choosing a backing type
- string: readable in the database and in URLs. Usually the best choice.
- int: compact, but you must remember what the numbers mean.
Enums in match
match ($status) { Status::Draft => ..., Status::Published => ... } reads clearly and fails loudly if you add a case and forget to handle it.