PHP 8.1 Enums
Ayesh Karunaratne | https://aye.sh/talk/php-enums-phpjp-2021

PHP 8.1 Enums

Ayesh Karunaratne | https://aye.sh/talk/php-enums-phpjp-2021

Ayesh Karunaratne
Freelance Software Developer, Security Researcher, Full-timetravelerKandy, Sri Lanka - Everywhere
https://aye.sh | https://php.watch@Ayeshlive | @phpwch
ayesh@aye.shPHP 8.1 Enums

PHP 8.1 Enumerations

PHP 8.1 Enumerations

PHP 8.1 Enumerations

04 Dec 2020

Enumerations: RFC Created

03 Feb 2021

Voting started

17 Feb 2021

Voting ended: 44:7

03 Oct 2021

PHP Conference Japan 2021

25 Nov 2021

PHP 8.1

PHP 8.1: Enums
Why we need Enums
How Enums can help
Enums in PHP 8.1
Enum Semantics

Usage Examples
Trying out Enums today
Backwards Compatibility

Why we need Enums

$handle = curl_init();$options = [CURLOPT_URL => 'https://example.com',
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0,
CURLOPT_RETURNTRANSFER => true,];
curl_setopt_array($handle, $options);
curl_exec($handle);

Why we need Enums

$handle = curl_init();$options = [CURLOPT_URL => 'https://example.com',
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0,
CURLOPT_RETURNTRANSFER => true,];
curl_setopt_array($handle, $options);
curl_exec($handle);

Why we need Enums

$handle = curl_init();$options = [CURLOPT_URL => 'https://example.com',
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0,
CURLOPT_RETURNTRANSFER => true,];
var_dump($options);
curl_setopt_array($handle, $options);
curl_exec($handle);

Why we need Enums

$handle = curl_init();array(3) {$options = [CURLOPT_URL => 'https://example.com',[10002]=> string(19) "https://example.com"
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0,[84]=> int(3)CURLOPT_RETURNTRANSFER => true,[19913]=> bool(true)];}
var_dump($options);
curl_setopt_array($handle, $options);
curl_exec($handle);

Why we need Enumsdefine ('CURLOPT_URL', 10002);
define ('CURLOPT_HTTP_VERSION', 84);
define ('CURL_HTTP_VERSION_1_1', 2);define ('CURL_HTTP_VERSION_2_0', 3);define ('CURLOPT_RETURNTRANSFER', 19913);$handle = curl_init();array(3) {$options = [CURLOPT_URL => 'https://example.com',[10002]=> string(19) "https://example.com"
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0,[84]=> int(3)CURLOPT_RETURNTRANSFER => true,[19913]=> bool(true)];}
var_dump($options);
curl_setopt_array($handle, $options);
curl_exec($handle);

Why we need Enumsdefine ('CURLOPT_URL', 10002);
define ('CURLOPT_HTTP_VERSION', 84);
define ('CURL_HTTP_VERSION_1_1', 2);define ('CURL_HTTP_VERSION_2_0', 3);define ('CURLOPT_RETURNTRANSFER', 19913);$handle = curl_init();array(3) {$options = [CURLOPT_URL => 'https://example.com',[10002]=> string(19) "https://example.com"
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0,[84]=> int(3)CURLOPT_RETURNTRANSFER => true,[19913]=> bool(true)];}
var_dump($options);
curl_setopt_array($handle, $options);
curl_exec($handle);

Why we need Enumsdefine ('CURLOPT_URL', 10002);
define ('CURLOPT_HTTP_VERSION', 84);
define ('CURL_HTTP_VERSION_1_1', 2);define ('CURL_HTTP_VERSION_2_0', 3);define ('CURLOPT_RETURNTRANSFER', 19913);$handle = curl_init();array(3) {$options = [CURLOPT_URL => 'https://example.com',[10002]=> string(19) "https://example.com"
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0,[84]=> int(3)CURLOPT_RETURNTRANSFER => true,[19913]=> bool(true)];}
var_dump($options);
curl_setopt_array($handle, $options);
curl_exec($handle);

Why we need Enums

function curl_setopt(CurlHandle $handle, int $option, mixed $value) : bool {}Why we need Enums

function curl_setopt(CurlHandle $handle, int $option, mixed $value) : bool {}Why we need Enums

function curl_setopt(CurlHandle $handle, int $option, mixed $value) : bool {}curl_setopt($handle, 10002, 'https://example.com');
10002 - CURLOPT_URL
curl_setopt($handle, 10003, 'https://example.com');

PHP Error: curl_setopt(): Argument #2 ($option) is not a valid cURL option in … on line …
curl_setopt($handle, 10004, 'https://example.com');
10004 - CURLOPT_PROXY

Why we need Enums

class Post {public const POST_STATUS_DRAFT = 'draft';public const POST_STATUS_PENDING = 'pending';
public const POST_STATUS_RETURNED = 'returned';public const POST_STATUS_PUBLISHED = 'published';
public string $status;}

public function updateStatus(string $status): void {}Why we need Enums

class Post {public const POST_STATUS_DRAFT = 'draft';public const POST_STATUS_PENDING = 'pending';
public const POST_STATUS_RETURNED = 'returned';public const POST_STATUS_PUBLISHED = 'published';
public string $status;}

public function updateStatus(string $status): void {}$post = new Post();$post->updateStatus(\Post::POST_STATUS_PUBLISHED);
Why we need Enums

class Post {public const POST_STATUS_DRAFT = 'draft';public const POST_STATUS_PENDING = 'pending';
public const POST_STATUS_RETURNED = 'returned';public const POST_STATUS_PUBLISHED = 'published';
public string $status;}

public function updateStatus(string $status): void {}$post = new Post();$post->updateStatus('returned');Why we need Enums

class Post {public const POST_STATUS_DRAFT = 'draft';public const POST_STATUS_PENDING = 'pending';
public const POST_STATUS_RETURNED = 'returned';public const POST_STATUS_PUBLISHED = 'published';
public string $status;}

public function updateStatus(string $status): void {}$post = new Post();$post->updateStatus('returned');Why we need Enums

class Post {public const POST_STATUS_DRAFT = 'draft';public const POST_STATUS_PENDING = 'pending';
public const POST_STATUS_RETURNED = 'returned';public const POST_STATUS_PUBLISHED = 'published';
public string $status;}

public function updateStatus(string $status): void {}Why we need Enums

class Post {public const POST_STATUS_DRAFT = 'draft';public const POST_STATUS_PENDING = 'pending';
public const POST_STATUS_RETURNED = 'returned';public const POST_STATUS_PUBLISHED = 'published';

public string $status;}

Why we need Enums

public function updateStatus(string $status): void {if ( $status !== static::POST_STATUS_DRAFT&& $status !== static::POST_STATUS_PENDING&& $status !== static::POST_STATUS_RETURNED&& $status !== static::POST_STATUS_PUBLISHED) {throw new InvalidArgumentException('Invalid state');}}class Post {public const POST_STATUS_DRAFT = 'draft';public const POST_STATUS_PENDING = 'pending';
public const POST_STATUS_RETURNED = 'returned';public const POST_STATUS_PUBLISHED = 'published';

public string $status;}

public function updateStatus(string $status): void {if ( $status !== static::POST_STATUS_DRAFT&& $status !== static::POST_STATUS_PENDING&& $status !== static::POST_STATUS_RETURNED&& $status !== static::POST_STATUS_PUBLISHED) {throw new InvalidArgumentException('Invalid state');}}https://en.wikipedia.org/wiki/Open-closed_principle
Why we need Enums

How Enums Can Helptype PostStatus = "draft" | "pending" | "returned" | "published";

How Enums Can Helptype PostStatus = "draft" | "pending" | "returned" | "published";
function updateStatus(status: PostStatus) {}How Enums Can Helptype PostStatus = "draft" | "pending" | "returned" | "published";
function updateStatus(status: PostStatus) {}How Enums Can Helptype PostStatus = "draft" | "pending" | "returned" | "published";
function updateStatus(status: PostStatus) {}updateStatus("draft");✔️

How Enums Can Help

updateStatus("potato");Argument of type '"potato"' is not assignable toparameter of type 'PostStatus'.

How Enums Can Helpenum PostStatus {DRAFT,PENDING,
PUBLISHED,
RETURNED,};
function updateStatus(status: PostStatus) {}updateStatus(PostStatus.DRAFT);How Enums Can Helpenum PostStatus {DRAFT = "draft",
PENDING = "pending",
PUBLISHED = "published",
RETURNED = "draft",};function updateStatus(status: PostStatus) {}updateStatus(PostStatus.DRAFT);How Enums Can Helpenum PostStatus {DRAFT = "draft",
PENDING = "pending",
PUBLISHED = "published",
RETURNED = "draft",};

How Enums Can Helpenum PostStatus {DRAFT = "draft";
PENDING = "pending";
PUBLISHED = "published";
RETURNED = "draft";};enum PostStatus {}How Enums Can Helpenum PostStatus {case DRAFT;
case PENDING;
case RETURNED;
case PUBLISHED;}How Enums Can Helpclass Post {public const POST_STATUS_DRAFT = 'draft';public const POST_STATUS_PENDING = 'pending';
public const POST_STATUS_RETURNED = 'returned';public const POST_STATUS_PUBLISHED = 'published';

public string $status;

enum PostStatus {case DRAFT;
case PENDING;
case RETURNED;
case PUBLISHED;}}

public function updateStatus(string $status): void {if ( $status !== static::POST_STATUS_DRAFT&& $status !== static::POST_STATUS_PENDING&& $status !== static::POST_STATUS_RETURNED&& $status !== static::POST_STATUS_PUBLISHED) {throw new InvalidArgumentException('Invalid state');}}$post = new Post();$post->updateStatus(\Post::POST_STATUS_PUBLISHED);
How Enums Can Helpclass Post {public const POST_STATUS_DRAFT = 'draft';public const POST_STATUS_PENDING = 'pending';
public const POST_STATUS_RETURNED = 'returned';public const POST_STATUS_PUBLISHED = 'published';

public string $status;

enum PostStatus {case DRAFT;
case PENDING;
case RETURNED;
case PUBLISHED;}}

public function updateStatus(string $status): void {if ( $status !== static::POST_STATUS_DRAFT&& $status !== static::POST_STATUS_PENDING&& $status !== static::POST_STATUS_RETURNED&& $status !== static::POST_STATUS_PUBLISHED) {throw new InvalidArgumentException('Invalid state');}}$post = new Post();$post->updateStatus(\Post::POST_STATUS_PUBLISHED);
How Enums Can Helpclass Post {public const POST_STATUS_DRAFT = 'draft';public const POST_STATUS_PENDING = 'pending';
public const POST_STATUS_RETURNED = 'returned';public const POST_STATUS_PUBLISHED = 'published';

public string $status;

enum PostStatus {case DRAFT;
case PENDING;
case RETURNED;
case PUBLISHED;}}

public function updateStatus(string $status): void {if ( $status !== static::POST_STATUS_DRAFT&& $status !== static::POST_STATUS_PENDING&& $status !== static::POST_STATUS_RETURNED&& $status !== static::POST_STATUS_PUBLISHED) {throw new InvalidArgumentException('Invalid state');}}$post = new Post();$post->updateStatus(\Post::POST_STATUS_PUBLISHED);
How Enums Can Helpclass Post {public const POST_STATUS_DRAFT = 'draft';public const POST_STATUS_PENDING = 'pending';
public const POST_STATUS_RETURNED = 'returned';public const POST_STATUS_PUBLISHED = 'published';

public PostStatus $status;

enum PostStatus {case DRAFT;
case PENDING;
case RETURNED;
case PUBLISHED;}}

public function updateStatus(string $status): void {if ( $status !== static::POST_STATUS_DRAFT&& $status !== static::POST_STATUS_PENDING&& $status !== static::POST_STATUS_RETURNED&& $status !== static::POST_STATUS_PUBLISHED) {throw new InvalidArgumentException('Invalid state');}}$post = new Post();$post->updateStatus(\Post::POST_STATUS_PUBLISHED);
How Enums Can Helpclass Post {public const POST_STATUS_DRAFT = 'draft';public const POST_STATUS_PENDING = 'pending';
public const POST_STATUS_RETURNED = 'returned';public const POST_STATUS_PUBLISHED = 'published';

public PostStatus $status;

enum PostStatus {case DRAFT;
case PENDING;
case RETURNED;
case PUBLISHED;}}

public function updateStatus(PostStatus $status): void {if ( $status !== static::POST_STATUS_DRAFT&& $status !== static::POST_STATUS_PENDING&& $status !== static::POST_STATUS_RETURNED&& $status !== static::POST_STATUS_PUBLISHED) {throw new InvalidArgumentException('Invalid state');}}$post = new Post();$post->updateStatus(\Post::POST_STATUS_PUBLISHED);
How Enums Can Helpclass Post {public const POST_STATUS_DRAFT = 'draft';public const POST_STATUS_PENDING = 'pending';
public const POST_STATUS_RETURNED = 'returned';public const POST_STATUS_PUBLISHED = 'published';

public PostStatus $status;

enum PostStatus {case DRAFT;
case PENDING;
case RETURNED;
case PUBLISHED;}}

public function updateStatus(PostStatus $status): void {if ( $status !== static::POST_STATUS_DRAFT&& $status !== static::POST_STATUS_PENDING&& $status !== static::POST_STATUS_RETURNED&& $status !== static::POST_STATUS_PUBLISHED) {throw new InvalidArgumentException('Invalid state');}}$post = new Post();$post->updateStatus(\Post::POST_STATUS_PUBLISHED);
How Enums Can Helpclass Post {public const POST_STATUS_DRAFT = 'draft';public const POST_STATUS_PENDING = 'pending';
public const POST_STATUS_RETURNED = 'returned';public const POST_STATUS_PUBLISHED = 'published';

public PostStatus $status;

enum PostStatus {case DRAFT;
case PENDING;
case RETURNED;
case PUBLISHED;}}

public function updateStatus(PostStatus $status): void {if ( $status !== static::POST_STATUS_DRAFT&& $status !== static::POST_STATUS_PENDING&& $status !== static::POST_STATUS_RETURNED&& $status !== static::POST_STATUS_PUBLISHED) {throw new InvalidArgumentException('Invalid state');}}$post = new Post();$post->updateStatus(\Post::POST_STATUS_PUBLISHED);
How Enums Can Helpclass Post {public const POST_STATUS_DRAFT = 'draft';public const POST_STATUS_PENDING = 'pending';
public const POST_STATUS_RETURNED = 'returned';public const POST_STATUS_PUBLISHED = 'published';

public PostStatus $status;

enum PostStatus {case DRAFT;
case PENDING;
case RETURNED;
case PUBLISHED;}}

public function updateStatus(PostStatus $status): void {if ( $status !== static::POST_STATUS_DRAFT&& $status !== static::POST_STATUS_PENDING&& $status !== static::POST_STATUS_RETURNED&& $status !== static::POST_STATUS_PUBLISHED) {throw new InvalidArgumentException('Invalid state');}}$post = new Post();$post->updateStatus(PostStatus::PUBLISHED);
How Enums Can Helpenum PostStatus {case DRAFT;
case PENDING;
case RETURNED;
case PUBLISHED;}How Enums Can Helpclass Post {public PostStatus $status;
public function updateStatus(PostStatus $status): void {}}$post = new Post();$post->updateStatus(\PostStatus::PUBLISHED);

function setIsSponsored(bool $sponsored): void {enum PostStatus {case DRAFT;
case PENDING;
case RETURNED;
case PUBLISHED;}How Enums Can Help}
function isSponsored(): bool {}setIsSponsored(true);
setIsSponsored(false);Enums in PHP 8.1

• Enums can have zero or more members

enum Suit {}Enums in PHP 8.1

• Enums can have zero or more members

enum Suit {case Clubs;case Diamonds;
case Spades;
case Hearts;}

Enums in PHP 8.1

• Enums can have zero or more members• Enum members are objects

enum Suit {case Clubs;case Diamonds;
case Spades;
case Hearts;}

is_object(Suit::Hearts);// true

Enums in PHP 8.1

• Enums can have zero or more members• Enum members are objects

enum Suit {case Clubs;case Diamonds;
case Spades;
case Hearts;}

var_dump(Suit::Hearts);// enum(Suit::Hearts)

Enums in PHP 8.1

• Enums can have zero or more members• Enum members are objects• Enums can be namespaced and autoloaded

namespace App\PlayingCards;
enum Suit {case Clubs;case Diamonds;
case Spades;
case Hearts;}

Enums in PHP 8.1

•
•
•
•

namespace App\PlayingCards;
enum Suit: int {case Clubs = 1;
case Diamonds = 2;case Spades = 3;case Hearts = 4;}

Enums in PHP 8.1

Enums can have zero or more members
Enum members are objects
Enums can be namespaced and autoloaded
May contain string|int backed values

•
•
•
•

namespace App\PlayingCards;
enum Suit: string {case Clubs = '♣️';case Diamonds = '♦️';case Spades = '♠️';case Hearts = '♥️';}

Enums in PHP 8.1

Enums can have zero or more members
Enum members are objects
Enums can be namespaced and autoloaded
May contain string|int backed values

namespace App\PlayingCards;

enum Suit: string {const AWESOME = 'Yes';}

case Clubs = '♣️';case Diamonds = '♦️';case Spades = '♠️';case Hearts = '♥️';

Enums in PHP 8.1

•
•
•
•
•

Enums can have zero or more members
Enum members are objects
Enums can be namespaced and autoloaded
May contain string|int backed values
May contain non-duplicated constants

namespace App\PlayingCards;
enum Suit: string {const AWESOME = 'Yes';

•
•
•
•
•
•

Enums can have zero or more members
Enum members are objects
Enums can be namespaced and autoloaded
May contain string|int backed values
May contain non-duplicated constants
May contain static methods

case Clubs = '♣️';case Diamonds = '♦️';case Spades = '♠️';case Hearts = '♥️';}

public static function cheer(): void {echo 'Yay!';}

Enums in PHP 8.1

Suit::cheer();// Yay!

namespace App\PlayingCards;
•
•
•
•
•
•
•

enum Suit: string {const AWESOME = 'Yes';

case Clubs = ' ';case Diamonds = ' ';case Spades = ' ';case Hearts = ' ';Enums can have zero or more members
Enum members are objects
Enums can be namespaced and autoloaded
May contain string|int backed values
May contain non-duplicated constants
May contain static methods
May contain non-static methods

public static function cheer(): void {echo 'Yay!';}}

public function show(): void {var_dump($this);
var_dump($this->name);
var_dump(self::Clubs->name);
var_dump($this->value);
var_dump(self::Clubs->value);}

Enums in PHP 8.1

Suit::Clubs->show();namespace App\PlayingCards;
•
•
•
•
•
•
•
•

enum Suit: string {const AWESOME = 'Yes';

case Clubs = ' ';case Diamonds = ' ';case Spades = ' ';case Hearts = ' ';Enums can have zero or more members
Enum members are objects
Enums can be namespaced and autoloaded
May contain string|int backed values
May contain non-duplicated constants
May contain static methods
May contain non-static methods$this refers to the Enumerated element

public static function cheer(): void {echo 'Yay!';}}

public function show(): void {var_dump($this);
var_dump($this->name);
var_dump(self::Clubs->name);
var_dump($this->value);
var_dump(self::Clubs->value);}

Enums in PHP 8.1

Suit::Clubs->show();enum(App\PlayingCards\Suit::Clubs)

namespace App\PlayingCards;
enum Suit: string {const AWESOME = 'Yes';

case Clubs = ' ';case Diamonds = ' ';case Spades = ' ';case Hearts = ' ';public static function cheer(): void {echo 'Yay!';}}

public function show(): void {var_dump($this);
var_dump($this->name);
var_dump(self::Clubs->name);
var_dump($this->value);
var_dump(self::Clubs->value);}

Enums in PHP 8.1

•
•
•
•
•
•
•
•
•

Enums can have zero or more members
Enum members are objects
Enums can be namespaced and autoloaded
May contain string|int backed values
May contain non-duplicated constants
May contain static methods
May contain non-static methods$this refers to the Enumerated element->name property is the name of the member

Suit::Clubs->show();enum(App\PlayingCards\Suit::Clubs)
string(5) "Clubs"
string(5) "Clubs"

namespace App\PlayingCards;
enum Suit: string {const AWESOME = 'Yes';

case Clubs = ' ';case Diamonds = ' ';case Spades = ' ';case Hearts = ' ';public static function cheer(): void {echo 'Yay!';}}

public function show(): void {var_dump($this);
var_dump($this->name);
var_dump(self::Clubs->name);
var_dump($this->value);
var_dump(self::Clubs->value);}

Enums in PHP 8.1

•
•
•
•
•
•
•
•
•
•

Enums can have zero or more members
Enum members are objects
Enums can be namespaced and autoloaded
May contain string|int backed values
May contain non-duplicated constants
May contain static methods
May contain non-static methods$this refers to the Enumerated element->name property is the name of the member->value property is the backed value

Suit::Clubs->show();enum(App\PlayingCards\Suit::Clubs)
string(5) "Clubs"
string(5) "Clubs"
string(6) "♣️"
string(6) "♣️"namespace App\PlayingCards;
enum Suit: string {const AWESOME = 'Yes';

case Clubs = ' ';case Diamonds = ' ';case Spades = ' ';case Hearts = ' ';public static function cheer(): void {echo 'Yay!';}}

public function show(): void {var_dump($this);
var_dump($this->name);
var_dump(self::Clubs->name);
var_dump($this->value);
var_dump(self::Clubs->value);}

Enums in PHP 8.1

•
•
•
•
•
•
•
•
•
•

Enums can have zero or more members
Enum members are objects
Enums can be namespaced and autoloaded
May contain string|int backed values
May contain non-duplicated constants
May contain static methods
May contain non-static methods$this refers to the Enumerated element->name property is the name of the member->value property is the backed value

Suit::Clubs->show();enum(App\PlayingCards\Suit::Clubs)
string(5) "Clubs"
string(5) "Clubs"
string(6) "♣️"
string(6) "♣️"

Unit Enums

enum PostStatus {case DRAFT;
case PENDING;
case RETURNED;
case PUBLISHED;}

Enums in PHP 8.1

Unit Enums

enum PostStatus implements UnitEnum {case DRAFT;
case PENDING;
case RETURNED;
case PUBLISHED;}

Enums in PHP 8.1

Unit Enums
interface UnitEnum {public static function cases(): array;}enum PostStatus implements UnitEnum {case DRAFT;
case PENDING;
case RETURNED;
case PUBLISHED;}

Enums in PHP 8.1

Unit Enums
interface UnitEnum {public static function cases(): array;}enum PostStatus implements UnitEnum {case DRAFT;
case PENDING;
case RETURNED;
case PUBLISHED;}

Enums in PHP 8.1

echo PostStatus::DRAFT->name;// "DRAFT"

Unit Enums
interface UnitEnum {public static function cases(): array;}enum PostStatus implements UnitEnum {case DRAFT;
case PENDING;
case RETURNED;
case PUBLISHED;}

Enums in PHP 8.1

echo PostStatus::DRAFT->name;// "DRAFT"

Unit Enums
interface UnitEnum {public static function cases(): array;}echo PostStatus::DRAFT->name;// "DRAFT"

enum PostStatus implements UnitEnum {case DRAFT;
case PENDING;
case RETURNED;
case PUBLISHED;}PostStatus::cases();

Enums in PHP 8.1

Unit Enums
interface UnitEnum {public static function cases(): array;}echo PostStatus::DRAFT->name;// "DRAFT"
PostStatus::cases();enum PostStatus implements UnitEnum {case DRAFT;
case PENDING;
case RETURNED;
case PUBLISHED;}

Enums in PHP 8.1

array(4) {[0]=> enum(PostStatus::DRAFT)[1]=> enum(PostStatus::PENDING)[2]=> enum(PostStatus::RETURNED)[3]=> enum(PostStatus::PUBLISHED)}Unit Enums
interface UnitEnum {public static function cases(): array;}echo PostStatus::DRAFT->name;// "DRAFT"
PostStatus::cases();enum PostStatus implements UnitEnum {case DRAFT;
case PENDING;
case RETURNED;
case PUBLISHED;}

Enums in PHP 8.1

array(4) {[0]=> enum(PostStatus::DRAFT)[1]=> enum(PostStatus::PENDING)[2]=> enum(PostStatus::RETURNED)[3]=> enum(PostStatus::PUBLISHED)}Backed Enums

Backed Enums extend Unit Enums

enum PostStatus: string {case DRAFT = 'draft';case PENDING = 'pending’;
case RETURNED = 'returned';case PUBLISHED = 'published';}

Enums in PHP 8.1

Backed Enums

Backed Enums extend Unit Enums

enum PostStatus: string implements BackedEnum {case DRAFT = 'draft';case PENDING = 'pending';case RETURNED = 'returned';case PUBLISHED = 'published';}

Enums in PHP 8.1

Backed Enums

Backed Enums extend Unit Enums
interface BackedEnum extends UnitEnum {public static function from(int|string $value): static;
public static function tryFrom(int|string $value): ?static;}enum PostStatus: string implements BackedEnum {case DRAFT = 'draft';case PENDING = 'pending';case RETURNED = 'returned';case PUBLISHED = 'published';}

Enums in PHP 8.1

Backed Enums

Backed Enums extend Unit Enums
interface BackedEnum extends UnitEnum {public static function from(
int|string $value): static;}

public static function tryFrom(
int|string $value): ?static;enum PostStatus: string implements BackedEnum {case DRAFT = 'draft';case PENDING = 'pending';case RETURNED = 'returned';case PUBLISHED = 'published';}

Enums in PHP 8.1

echo PostStatus::DRAFT->name;// "DRAFT"

Backed Enums

Backed Enums extend Unit Enums
interface BackedEnum extends UnitEnum {public static function from(
int|string $value): static;}

public static function tryFrom(
int|string $value): ?static;enum PostStatus: string implements BackedEnum {case DRAFT = 'draft';case PENDING = 'pending';case RETURNED = 'returned';case PUBLISHED = 'published';}

Enums in PHP 8.1

echo PostStatus::DRAFT->name;// "DRAFT"

Backed Enums

Backed Enums extend Unit Enums
interface BackedEnum extends UnitEnum {public static function from(
int|string $value): static;}echo PostStatus::DRAFT->name;// "DRAFT"

public static function tryFrom(
int|string $value): ?static;enum PostStatus: string implements BackedEnum {case DRAFT = 'draft';case PENDING = 'pending';case RETURNED = 'returned';case PUBLISHED = 'published';}

Enums in PHP 8.1

echo PostStatus::DRAFT->value;// "draft"

Backed Enums

Backed Enums extend Unit Enums
interface BackedEnum extends UnitEnum {public static function from(
int|string $value): static;echo PostStatus::DRAFT->name;// "DRAFT"

public static function tryFrom(
int|string $value): ?static;echo PostStatus::DRAFT->value;// "draft"}enum PostStatus: string implements BackedEnum {case DRAFT = 'draft';case PENDING = 'pending';case RETURNED = 'returned';case PUBLISHED = 'published';}

Enums in PHP 8.1

PostStatus::tryFrom('draft');
PostStatus::from('draft');

Backed Enums

Backed Enums extend Unit Enums
interface BackedEnum extends UnitEnum {public static function from(
int|string $value): static;echo PostStatus::DRAFT->name;// "DRAFT"

public static function tryFrom(
int|string $value): ?static;echo PostStatus::DRAFT->value;// "draft"}enum PostStatus: string implements BackedEnum {case DRAFT = 'draft';case PENDING = 'pending';case RETURNED = 'returned';case PUBLISHED = 'published';}

Enums in PHP 8.1

PostStatus::tryFrom('draft');
PostStatus::from('draft');

Backed Enums

Backed Enums extend Unit Enums
interface BackedEnum extends UnitEnum {public static function from(
int|string $value): static;echo PostStatus::DRAFT->name;// "DRAFT"

public static function tryFrom(
int|string $value): ?static;echo PostStatus::DRAFT->value;// "draft"}enum PostStatus: string implements BackedEnum {case DRAFT = 'draft';case PENDING = 'pending';case RETURNED = 'returned';case PUBLISHED = 'published';}

Enums in PHP 8.1

PostStatus::tryFrom('draft');
PostStatus::from('draft');

Backed Enums

Backed Enums extend Unit Enums
interface BackedEnum extends UnitEnum {public static function from(
int|string $value): static;echo PostStatus::DRAFT->name;// "DRAFT"

public static function tryFrom(
int|string $value): ?static;echo PostStatus::DRAFT->value;// "draft"}enum PostStatus: string implements BackedEnum {case DRAFT = 'draft';case PENDING = 'pending';case RETURNED = 'returned';case PUBLISHED = 'published';}

Enums in PHP 8.1

PostStatus::tryFrom('draft');
PostStatus::from('draft');enum(PostStatus::DRAFT)

Backed Enums

Backed Enums extend Unit Enums
interface BackedEnum extends UnitEnum {public static function from(
int|string $value): static;}

public static function tryFrom(
int|string $value): ?static;enum PostStatus: string implements BackedEnum {case DRAFT = 'draft';case PENDING = 'pending';case RETURNED = 'returned';case PUBLISHED = 'published';}

echo PostStatus::DRAFT->name;// "DRAFT"
echo PostStatus::DRAFT->value;// "draft"
PostStatus::tryFrom('draft');
PostStatus::from('draft');enum(PostStatus::DRAFT)

PostStatus::tryFrom('potato');PostStatus::from('potato');Enums in PHP 8.1

Backed Enums

Backed Enums extend Unit Enums
interface BackedEnum extends UnitEnum {public static function from(
int|string $value): static;}

public static function tryFrom(
int|string $value): ?static;enum PostStatus: string implements BackedEnum {case DRAFT = 'draft';case PENDING = 'pending';case RETURNED = 'returned';case PUBLISHED = 'published';}

echo PostStatus::DRAFT->name;// "DRAFT"
echo PostStatus::DRAFT->value;// "draft"
PostStatus::tryFrom('draft');
PostStatus::from('draft');enum(PostStatus::DRAFT)

PostStatus::tryFrom('potato');PostStatus::from('potato');Enums in PHP 8.1

Backed Enums

Backed Enums extend Unit Enums
interface BackedEnum extends UnitEnum {public static function from(
int|string $value): static;}

public static function tryFrom(
int|string $value): ?static;enum PostStatus: string implements BackedEnum {case DRAFT = 'draft';case PENDING = 'pending';case RETURNED = 'returned';case PUBLISHED = 'published';}

echo PostStatus::DRAFT->name;// "DRAFT"
echo PostStatus::DRAFT->value;// "draft"
PostStatus::tryFrom('draft');
PostStatus::from('draft');enum(PostStatus::DRAFT)

PostStatus::tryFrom('potato');// null
PostStatus::from('potato');Uncaught ValueError: "potato" is not a valid backing value
for enum "PostStatus"

Enums in PHP 8.1

Backed Enums

Backed Enums extend Unit Enums
interface BackedEnum extends UnitEnum {public static function from(
int|string $value): static;}

public static function tryFrom(
int|string $value): ?static;enum PostStatus: string implements BackedEnum {case DRAFT = 'draft';case PENDING = 'pending';case RETURNED = 'returned';case PUBLISHED = 'published';}

echo PostStatus::DRAFT->name;// "DRAFT"
echo PostStatus::DRAFT->value;// "draft"
PostStatus::tryFrom('draft');
PostStatus::from('draft');enum(PostStatus::DRAFT)

PostStatus::tryFrom('potato');// null
PostStatus::from('potato');Uncaught ValueError: "potato" is not a valid backing value
for enum "PostStatus"

Enums in PHP 8.1

Enum Semantics

Enum
Enumerated type that contains a fixed number of members.

Enum Semantics

Enum
Enumerated type that contains a fixed number of members.
A type that is supported as parameter, return, and property type in PHP,
and the type is enforced by PHP itself.

Enum Semantics

Enum
Enumerated type that contains a fixed number of members.
All members are contained within a declared Enum.

Enum Semantics

Enum
Enumerated type that contains a fixed number of members.
Members of an Enum is fixed at the declaration time.
An enumerated member is identical to the same member everywhere.
Enums must not contain state.

Enum Semantics

Enumerated types

function play_card(Suit $suit, string $card) {}enum Suit {case Spades;
case Hearts;
case Clubs;case Diamonds;}

Enum Semantics

function pick_a_suit(): Suit {return Suit::Spades;}

play_card(Suit::Spades, 'A');
var_dump(pick_a_suit());// enum(Suit::Spades)

Enumerated types

function play_card(Suit $suit, string $card) {}enum Suit {case Spades;
case Hearts;
case Clubs;case Diamonds;}

function pick_a_suit(): Suit {return Suit::Spades;}
play_card(Fruits::Apple);play_card(Languages::English);play_card('potato');Fatal error: Uncaught TypeError: play_card(): Argument #1($suit) must be of type Suit, string given

Enum Semantics

Closed Set

enum Suit {case Spades;
case Hearts;
case Clubs;case Diamonds;}

Enum Semantics

Fixed Members
enum Suit {case Spades;
case Hearts;
case Clubs;case Diamonds;}

Enum Semantics

Suit::Spades === Suit::Spades

Fixed Members
enum Suit {case Spades;
case Hearts;
case Clubs;case Diamonds;}

Enum Semantics

enum RussianSuit extends Suit {}Parse error: syntax error, unexpected token "extends",
expecting "{"No Properties Allowed
enum Suit {case Spades;
case Hearts;
case Clubs;case Diamonds;}

private string $foo;

Fatal error: Enums may not include properties

Enum Semantics

Backed Enums must assign values for all cases

enum HTTPMethods: string {case GET;
case POST;}
Fatal error: Case GET of backed enum HTTPMethods must have a value

Enum Semantics

Enum cases and values must be uniqueenum Test {case FOO;
case FOO;}
Fatal error: Cannot redefine classconstant Test::FOO

Enum Semantics

enum Test: string {case FOO = 'baz';case BAR = 'baz';}Fatal error: Duplicate value inenum Test for cases FOO and BAR

Class Semantics

namespace Foo\Bar;enum PostStatus: string implements EntityStatues {

•
•
•
•
•
•

use TestTrait;

Supports namespaces
Supports traits
Supports autoloading
Supports magic constants
Supports instanceof
Supports methods

case DRAFT = 'draft';case PENDING = 'pending';case RETURNED = 'returned';case PUBLISHED = 'published’;
public static function showOff(): void {echo __CLASS__ . static::class;}}

Enum Semantics

Usage Examples

enum PostStatus: string {case DRAFT = 'draft';case PENDING = 'pending’;
case RETURNED = 'returned';case PUBLISHED = 'published';}

Usage Examples

class Post {private int $id;
private string $title;
private PostStatus $status;
public function __construct(
int $id,string $title,
PostStatus $status) {// ...
}

enum PostStatus: string {case DRAFT = 'draft';case PENDING = 'pending’;
case RETURNED = 'returned';case PUBLISHED = 'published';}}

Usage Examples

public function getStatus(): PostStatus {return $this->status;}

class Post {private int $id;
private string $title;
private PostStatus $status;
public function __construct(
int $id,string $title,
PostStatus $status) {// ...
}

enum PostStatus: string {case DRAFT = 'draft';case PENDING = 'pending’;
case RETURNED = 'returned';case PUBLISHED = 'published';}}

Usage Examples

public function getStatus(): PostStatus {return $this->status;}

class Post {private int $id;
private string $title;
private PostStatus $status;
public function __construct(
int $id,string $title,
PostStatus $status) {// ...
}

enum PostStatus: string {case DRAFT = 'draft';case PENDING = 'pending’;
case RETURNED = 'returned';case PUBLISHED = 'published';}}

Usage Examples

public function getStatus(): PostStatus {return $this->status;}

class Post {private int $id;
private string $title;
private PostStatus $status;
public function __construct(
int $id,string $title,
PostStatus $status) {// ...
}

enum PostStatus: string {case DRAFT = 'draft';case PENDING = 'pending’;
case RETURNED = 'returned';case PUBLISHED = 'published';}}

Usage Examples

public function getStatus(): PostStatus {return $this->status;}

enum PostStatus: string {case DRAFT = 'draft';case PENDING = 'pending’;
case RETURNED = 'returned';case PUBLISHED = 'published';}class Post {private int $id;
private string $title;
private PostStatus $status;
public function __construct(
int $id,string $title,
PostStatus $status) {// ...
}}

public function getStatus(): PostStatus {return $this->status;}

Usage Examples$stmt = $pdo->prepare("
SELECT *FROM posts
WHERE post_status=?");$stmt->execute([
PostStatus::PUBLISHED->value]);$post = $stmt->fetch();enum PostStatus: string {case DRAFT = 'draft';case PENDING = 'pending’;
case RETURNED = 'returned';case PUBLISHED = 'published';}class Post {private int $id;
private string $title;
private PostStatus $status;
public function __construct(
int $id,string $title,
PostStatus $status) {// ...
}}

public function getStatus(): PostStatus {return $this->status;}

Usage Examples$stmt = $pdo->prepare("
SELECT *FROM posts
WHERE post_status=?");$stmt->execute([
PostStatus::PUBLISHED->value]);$post = $stmt->fetch();enum PostStatus: string {case DRAFT = 'draft';case PENDING = 'pending’;
case RETURNED = 'returned';case PUBLISHED = 'published';}class Post {private int $id;
private string $title;
private PostStatus $status;
public function __construct(
int $id,string $title,
PostStatus $status) {// ...
}}

public function getStatus(): PostStatus {return $this->status;}

Usage Examples$sql = "INSERT INTO
posts (id, title, post_status)
VALUES(:id, :title, :post_status)";$stmt= $pdo->prepare($sql);$stmt->execute(['id' => $post->getId(),'title' => $post->getTitle(),'post_status' => $post->getStatus()->value,]);enum PostStatus: string {case DRAFT = 'draft';case PENDING = 'pending’;
case RETURNED = 'returned';case PUBLISHED = 'published';}class Post {private int $id;
private string $title;
private PostStatus $status;
public function __construct(
int $id,string $title,
PostStatus $status) {// ...
}}

public function getStatus(): PostStatus {return $this->status;}

Usage Examples$sql = "INSERT INTO
posts (id, title, post_status)
VALUES(:id, :title, :post_status)";$stmt= $pdo->prepare($sql);$stmt->execute(['id' => $post->getId(),'title' => $post->getTitle(),'post_status' => $post->getStatus()->value,]);enum PostStatus: string {case DRAFT = 'draft';case PENDING = 'pending’;
case RETURNED = 'returned';case PUBLISHED = 'published';}class Post {private int $id;
private string $title;
private PostStatus $status;

public function __construct(
int $id,string $title,
PostStatus $status) {// ...
}$post = new Post($result['id'],$result['title']);

public function getStatus(): PostStatus {return $this->status;}$post->updateStatus(
PostStatus::from($result['post_status']));public function updateStatus(
PostStatus $status): void {}$result = ['id' => 42,'title' => 'PHP Enums','post_status' => 'published',];}

Usage Examples

enum PostStatus: string {case DRAFT = 'draft';case PENDING = 'pending’;
case RETURNED = 'returned';case PUBLISHED = 'published';}class Post {private int $id;
private string $title;
private PostStatus $status;

public function __construct(
int $id,string $title,
PostStatus $status) {// ...
}$post = new Post($result['id'],$result['title']);

public function getStatus(): PostStatus {return $this->status;}$post->updateStatus(
PostStatus::from($result['post_status']));public function updateStatus(
PostStatus $status): void {}$result = ['id' => 42,'title' => 'PHP Enums','post_status' => 'published',];}

Usage Examples

Trying out Enums today

Try it online with 3v4l.org

Trying out Enums today

Nightly Docker Images

docker pull phpdaily/php:8.1-dev

Trying out Enums todaySelf-compile PHP from source
$
$
$
$
$

git clone git@github.com:php/php-src.git./buildconf./configure
make -j$(nproc)./sapi/cli/php -a

https://php.watch/articles/compile-php-ubuntu
Trying out Enums today

Backwards Compatibility

Enums is a new syntax

Enums is a new syntax introduced in PHP 8.1, and notsupported in older PHP versions.

Parse error: syntax error, unexpected identifier "PostStatus"

Backwards Compatibility

User-land PHP implementations
https://github.com/myclabs/php-enum

use MyCLabs\Enum\Enum;class PostStatus extends Enum {private const DRAFT = 'draft';private const PENDING = 'pending';
private const RETURNED = 'returned';
private const PUBLISHED = 'published';}

Backwards Compatibility

Further Resources••••

https://aye.sh/talk/php-enums-phpjp-2021
https://php.watch/versions/8.1/enums
https://php.watch/versions/8.1
https://wiki.php.net/rfc/enumerations

•
•
•
•
•
•

https://phpinternals.news/73
https://github.com/php/php-src/pull/6489/
https://externals.io/message/112626
https://github.com/phpdaily/php
https://3v4l.org/
https://php.watch/articles/compile-php-ubuntu

Questions?
No question is too small.

@Ayeshlive ayesh@php.watch
https://aye.sh/talk/php-enums-phpjp-2021dziękuję

Ďakujemtakpaldiesarigatômahalo kop khun
grazie děkuji
diolchdankieköszönömxвалаshukrancảm ơn bạn
tänanБаярлалаа
a dank gràcies
dhanyavādДякую ευχαριστώ
Благодарам
благодаря
спасибо
ありがとうございました tackngiyabonga
graciasБлагодарятиDankumulţumesc M̀h’gōi‫תודה‬.
ačiū
ස්ත
ු
තියි
nandritakk
danke
faleminderit
Xièxiè
choukraneteşekkür ederimobrigado
kiitosՇնորհակալություն
terima kasih hvalagrazziThank YouPHP 8.1 Enums

Ayesh Karunaratne | https://aye.sh/talk/php-enums-phpjp-2021