Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

PHP Dictionary

  1. Home
  2. PHP Dictionary
  3. enum (Enumerations)

enum (Enumerations)

Since: PHP 8.1(2021)

To handle a fixed set of values in a type-safe way, the『enum』(enumeration type) added in『PHP』8.1 is useful. Instead of passing "states" or "categories" around as constants or strings, defining them as a dedicated type makes the intent of the code clear and prevents invalid values from being assigned at compile time.

Syntax

// Pure enum (enumeration without a backing value)
enum EnumName {
	case CaseName;
}

// Backed enum (enumeration with int or string values)
enum EnumName: int {
	case CaseName = value;
}

enum EnumName: string {
	case CaseName = 'value';
}

// Accessing an enum case
EnumName::CaseName

// Getting a case from a value in a Backed enum
EnumName::from(value) // throws ValueError if no match
EnumName::tryFrom(value) // returns null if no match

Differences Between Pure Enum and Backed Enum

TypeSyntaxDescription
Pure enumenum Name { case ... }Does not hold a scalar value such as an integer or string. The case itself is treated as an object.
Backed enum (int)enum Name: int { case ... = value }Assigns an integer value to each case. Convenient for storage in databases.
Backed enum (string)enum Name: string { case ... = 'value' }Assigns a string value to each case. Convenient for interacting with JSON or external APIs.

Enum Properties and Methods

NameAvailable inDescription
$case->namePure enum / Backed enumReturns the case name as a string. Example:『Suit::Hearts->name』returns『"Hearts"』.
$case->valueBacked enum onlyReturns the scalar value assigned to the case. Not available in Pure enums.
::from($value)Backed enum onlyRetrieves a case from a scalar value. Throws a『ValueError』if no matching case exists.
::tryFrom($value)Backed enum onlyRetrieves a case from a scalar value. Returns『null』if no matching case exists.
::cases()Pure enum / Backed enumReturns an array of all cases.

Sample Code

Pure Enum Basics
enum_pure.php
<?php
// Define KOF character attributes using a Pure enum
// Pure enums hold no scalar value; the case itself is an object
enum Element {
	case Fire; // fire
	case Ice; // ice
	case Thunder; // lightning
	case Wind; // wind
}

// Cases are accessed like class constants
$kyo = Element::Fire;
$iori = Element::Fire;
$kula = Element::Ice;
$benimaru = Element::Thunder;

// Identical cases match with strict comparison (===)
var_dump($kyo === $iori); // true — same case
var_dump($kyo === $kula); // false — different case

// ->name retrieves the case name as a string
echo $kyo->name . "\n"; // Fire
echo $kula->name . "\n"; // Ice

// Combined with a match expression for per-case logic
function getElementDescription(Element $element): string
{
	return match($element) {
		Element::Fire => "Kusanagi Kyo uses fire.",
		Element::Ice => "Kula uses ice.",
		Element::Thunder => "Benimaru uses lightning.",
		Element::Wind => "This fighter uses wind.",
	};
}

echo "草薙京: " . getElementDescription($kyo) . "\n";
echo "クーラ: " . getElementDescription($kula) . "\n";
echo "八神庵: " . getElementDescription($iori) . "\n";
echo "二階堂紅丸: " . getElementDescription($benimaru) . "\n";

Running the code produces the following output:

php enum_pure.php
bool(true)
bool(false)
Fire
Ice
草薙京: Kusanagi Kyo uses fire.
クーラ: Kula uses ice.
八神庵: Kusanagi Kyo uses fire.
二階堂紅丸: Benimaru uses lightning.
Backed Enum (int)
enum_backed_int.php
<?php
// Define KOF character ranks using an int-backed enum
// Assigning integer values to each case makes them usable for database storage
enum Rank: int {
	case D = 1;
	case C = 2;
	case B = 3;
	case A = 4;
	case S = 5;
}

// ->value retrieves the integer value assigned to the case
echo Rank::A->value . "\n"; // 4
echo Rank::S->name . "\n"; // S

// ::from() retrieves a case from an integer value
// Throws ValueError if no matching case exists
$rank = Rank::from(3);
echo $rank->name . "\n"; // B

// ::tryFrom() returns null when no case is found (no exception)
$unknownRank = Rank::tryFrom(99);
var_dump($unknownRank); // NULL

// Example combining characters with ranks
$fighters = [
	["name" => "草薙京", "rank" => Rank::S],
	["name" => "八神庵", "rank" => Rank::S],
	["name" => "テリー・ボガード", "rank" => Rank::A],
	["name" => "ラルフ・ジョーンズ", "rank" => Rank::B],
];

foreach ($fighters as $fighter) {
	// ->value for integer, ->name for case name
	echo $fighter['name'] . ": Rank " . $fighter['rank']->name
		. " (score: " . $fighter['rank']->value . ")\n";
}

Running the code produces the following output:

php enum_backed_int.php
4
S
B
NULL
草薙京: Rank S (score: 5)
八神庵: Rank S (score: 5)
テリー・ボガード: Rank A (score: 4)
ラルフ・ジョーンズ: Rank B (score: 3)
Backed Enum (string)
enum_backed_string.php
<?php
// Define KOF teams using a string-backed enum
// Useful when string values are needed for external APIs or JSON
enum Team: string {
	case HeroesTeam = 'heroes';
	case RivalsTeam = 'rivals';
	case FatalFury = 'fatal_fury';
	case IkariTeam = 'ikari';
}

// ->value retrieves the string value
echo Team::HeroesTeam->value . "\n"; // heroes
echo Team::FatalFury->value . "\n"; // fatal_fury

// ::from() restores a case from a string value (e.g., value read from JSON)
$teamFromJson = Team::from('ikari');
echo $teamFromJson->name . "\n"; // IkariTeam

// ::cases() returns an array of all cases
echo "--- All Teams ---\n";
foreach (Team::cases() as $team) {
	echo $team->name . ": " . $team->value . "\n";
}

// Example of character-team mappings
$members = [
	["name" => "草薙京", "team" => Team::HeroesTeam],
	["name" => "八神庵", "team" => Team::RivalsTeam],
	["name" => "テリー・ボガード", "team" => Team::FatalFury],
	["name" => "ラルフ・ジョーンズ", "team" => Team::IkariTeam],
];

echo "\n--- Team Assignments ---\n";
foreach ($members as $member) {
	// Use ->value when sending JSON or saving to DB
	echo $member['name'] . ": " . $member['team']->value . "\n";
}

Running the code produces the following output:

php enum_backed_string.php
heroes
fatal_fury
IkariTeam
--- All Teams ---
HeroesTeam: heroes
RivalsTeam: rivals
FatalFury: fatal_fury
IkariTeam: ikari

--- Team Assignments ---
草薙京: heroes
八神庵: rivals
テリー・ボガード: fatal_fury
ラルフ・ジョーンズ: ikari
Defining Methods and Implementing Interfaces on Enums
enum_method_interface.php
<?php
// Methods can be defined on enums
// Enums can also implement interfaces

// Define an interface for retrieving a label
interface HasLabel {
	public function label(): string;
}

// Define KOF fighting styles as a string-backed enum implementing the interface
enum FightingStyle: string implements HasLabel {
	case Karate = 'karate';
	case Muay_Thai = 'muay_thai';
	case Wrestling = 'wrestling';
	case Martial_Art = 'martial_art';

	// Implement the interface method
	public function label(): string
	{
		return match($this) {
			FightingStyle::Karate => "Karate",
			FightingStyle::Muay_Thai => "Muay Thai",
			FightingStyle::Wrestling => "Wrestling",
			FightingStyle::Martial_Art => "Martial Arts",
		};
	}

	// Additional custom method on the enum
	public function description(): string
	{
		return match($this) {
			FightingStyle::Karate => "Kusanagi-style karate. Features flame-imbued attacks.",
			FightingStyle::Muay_Thai => "Muay Thai practitioner. Powerful kick techniques.",
			FightingStyle::Wrestling => "Wrestling-based throws are a strong point.",
			FightingStyle::Martial_Art => "Chinese martial arts. Agile and varied techniques.",
		};
	}
}

// Call the method via the interface
function printStyle(HasLabel $style): void
{
	echo $style->label() . "\n";
}

$style = FightingStyle::Karate;
printStyle($style); // Karate

// Call each method
$fighters = [
	["name" => "草薙京", "style" => FightingStyle::Karate],
	["name" => "キム・カッファン", "style" => FightingStyle::Muay_Thai],
	["name" => "クラーク・スティル", "style" => FightingStyle::Wrestling],
	["name" => "レオナ・ハイデルン", "style" => FightingStyle::Martial_Art],
];

foreach ($fighters as $fighter) {
	echo $fighter['name'] . " (" . $fighter['style']->label() . "): "
		. $fighter['style']->description() . "\n";
}

// Can also be restored from a value and used
$fromValue = FightingStyle::from('muay_thai');
echo "\nRestored style: " . $fromValue->label() . "\n";

Running the code produces the following output:

php enum_method_interface.php
Karate
草薙京 (Karate): Kusanagi-style karate. Features flame-imbued attacks.
キム・カッファン (Muay Thai): Muay Thai practitioner. Powerful kick techniques.
クラーク・スティル (Wrestling): Wrestling-based throws are a strong point.
レオナ・ハイデルン (Martial Arts): Chinese martial arts. Agile and varied techniques.

Restored style: Muay Thai

Common Mistakes

Trying to access ->value on a Pure enum

Pure enums do not hold a scalar value, so accessing ->value causes a fatal error. ->value is exclusive to Backed enums.

ng_enum_value.php
<?php
enum Element {
	case Fire;
	case Ice;
}

$kyo = Element::Fire;
echo $kyo->value . "\n"; // Pure enum has no value, causes an error

Running the code produces the following output:

php ng_enum_value.php
Fatal error: Uncaught Error: Cannot access the value of a non-backed enum in ng_enum_value.php:8

Use a Backed enum when scalar values are needed. When no value is required, ->name retrieves the case name as a string.

ok_enum_value.php
<?php
// Pure enum: use ->name to get the case name
enum Element {
	case Fire;
	case Ice;
}

$kyo = Element::Fire;
echo $kyo->name . "\n"; // "Fire"

// Backed enum: use ->value to get the scalar value
enum ElementBacked: string {
	case Fire = 'fire';
	case Ice = 'ice';
}

$iori = ElementBacked::Fire;
echo $iori->value . "\n"; // "fire"

Running the code produces the following output:

php ok_enum_value.php
Fire
fire

Passing a non-existent value to ::from()

::from() throws a ValueError when no matching case is found. If an unknown value enters from external input without exception handling, the script will stop.

ng_enum_from.php
<?php
enum Rank: int {
	case D = 1;
	case C = 2;
	case B = 3;
	case A = 4;
	case S = 5;
}

// Passing the non-existent value 99 to from() raises a ValueError
$rank = Rank::from(99);
echo $rank->name . "\n";

Running the code produces the following output:

php ng_enum_from.php
Fatal error: Uncaught ValueError: 99 is not a valid backing value for enum "Rank" in ng_enum_from.php:13

When the value may not be valid—such as from external input—use ::tryFrom(), which returns null, and add a null check.

ok_enum_from.php
<?php
enum Rank: int {
	case D = 1;
	case C = 2;
	case B = 3;
	case A = 4;
	case S = 5;
}

$fighters = [
	["name" => "草薙京", "rankValue" => 5],
	["name" => "テリー・ボガード", "rankValue" => 4],
	["name" => "Unknown fighter", "rankValue" => 99],
];

foreach ($fighters as $fighter) {
	$rank = Rank::tryFrom($fighter['rankValue']);
	if ($rank !== null) {
		echo $fighter['name'] . ": Rank " . $rank->name . "\n";
	} else {
		echo $fighter['name'] . ": Unknown rank\n";
	}
}

Running the code produces the following output:

php ok_enum_from.php
草薙京: Rank S
テリー・ボガード: Rank A
Unknown fighter: Unknown rank

Summary

『enum』is a syntax added in PHP 8.1 that defines a fixed set of values as a type. Representing "states" and "categories" that were previously handled as constants or strings as a dedicated type means that,when combined with type hints, invalid values can be rejected at compile time and IDE autocompletion becomes available.

There are two kinds:『Pure enum』, which holds no scalar value, and『Backed enum』, which holds an int or string value. With Backed enums,『::from()』allows restoring a case from a value, making them well-suited for interacting with databases and external APIs. When an invalid value may be passed, use『::tryFrom()』, which returns『null』rather than throwing an exception as『::from()』does.

Methods can be defined on an『enum』, and interfaces can be implemented. This allows designing cases to hold their own logic, rather than writing per-case handling in a『match』expression. For『match』expressions, see『match expression』. For interfaces, see『extends / implements』.

If you find any errors or copyright issues, please .