Skip to content

PHP Tutorial Modern PHP Features

Backed Enums

Lesson 228 of 369 2 min read By Deepak Paswan Updated Oct 5, 2026

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.

index.php
PHP
<?php
enum Status: string
{
    case Draft = "draft";
    case Published = "published";
    case Archived = "archived";
}

echo Status::Published->value . "\n";
echo Status::Published->name;
Output
OUTPUT
published
Published
  • : string after the enum name makes it “string-backed”. Use : int for numbers.
  • Every case needs a value, and values must be unique.
  • ->value is the stored value, ->name is the case name.

From a value to a case: from() and tryFrom()

index.php
PHP
<?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();
}
Output
OUTPUT
Published
NULL
"deleted" is not a valid backing value for enum Status
  • from() throws a ValueError if the value does not exist.
  • tryFrom() returns null instead.

Validating input

tryFrom() is perfect for validating form or URL input against the allowed options.

index.php
PHP
<?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;
Output
OUTPUT
newest

Only real cases get through. Everything else falls back to the default.

Save to and load from a database

index.php
PHP
<?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;
Output
OUTPUT
Stored: editor
Loaded: Editor

Build a select list

index.php
PHP
<?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";
}
Output
OUTPUT
<option value="IN">India</option>
<option value="NP">Nepal</option>

JSON

A backed enum converts to its value in json_encode().

index.php
PHP
<?php
enum Status: string
{
    case Draft = "draft";
}

echo json_encode(["status" => Status::Draft]);
Output
OUTPUT
{"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.
lightbulb
Enums in match
match ($status) { Status::Draft => ..., Status::Published => ... } reads clearly and fails loudly if you add a case and forget to handle it.