Since PHP 8.1, we can use enumerations also called enums. Enum defines a custom type that contains a fixed set of related values.
Enum is declared using the enum
keyword followed by the name. Each value is declared with the case
keyword.
<?php
enum UserStatus
{
case ACTIVE;
case NOT_ACTIVE;
case PENDING;
case DELETED;
}
Enums can be used anywhere where types are accepted: parameters, return values, and properties.
<?php
class User
{
private UserStatus $status;
public function getStatus(): UserStatus
{
return $this->status;
}
public function setStatus(UserStatus $status): void
{
$this->status = $status;
}
}
Only allowable values of enum type can be passed to a function or class method that accepts a parameter with enum type.
<?php
require_once 'UserStatus.php';
require_once 'User.php';
$user = new User();
$user->setStatus(UserStatus::ACTIVE);
Zero or more cases
Enum may have any number of case
definitions, from zero to unlimited. Enum without any case
is valid, but not very useful.
<?php
enum UserStatus
{
}
Case-sensitive name of the case
The name of the case is case-sensitive. The following example is valid but not recommended:
<?php
enum UserStatus
{
case ACTIVE;
case active;
}
Backed enums
Each case in enum may have a scalar value. Enum that contains case
definitions with values is called backed enum.
<?php
enum UserStatus: string
{
case ACTIVE = 'A';
case NOT_ACTIVE = 'N';
case PENDING = 'P';
case DELETED = 'D';
}
There are some important notes for backed enums:
- Type must be specified in enum declaration. Only
string
orint
types are allowed. For example, the following example is wrong becausefloat
cannot be used as a type for enum values:
enum UserStatus: float // Error
{
}
- All cases must have values. For example, the following example is wrong because
NOT_ACTIVE
doesn't have value:
<?php
enum UserStatus: string
{
case ACTIVE = 'A';
case NOT_ACTIVE; // Error
}
- Values must be of the same type. For example, the following example is wrong because
NOT_ACTIVE
must haveint
value instead ofstring
:
<?php
enum UserStatus: int
{
case ACTIVE = 1;
case NOT_ACTIVE = '2'; // Error
}
- Values must be unique. For example, the following example is wrong because
NOT_ACTIVE
has value1
which already used:
<?php
enum UserStatus: int
{
case ACTIVE = 1;
case NOT_ACTIVE = 1; // Error
}
Enum methods
Enum may have methods, just like class. It supports visibility modifiers such as public
, protected
or private
.
<?php
enum UserStatus
{
case ACTIVE;
case NOT_ACTIVE;
public function getLabel(): string
{
return match ($this) {
self::ACTIVE => 'Active',
self::NOT_ACTIVE => 'Not active',
};
}
}
<?php
require_once 'UserStatus.php';
echo UserStatus::ACTIVE->getLabel(); // Active
Static methods supported as well.
<?php
enum UserStatus
{
case ACTIVE;
case NOT_ACTIVE;
public static function getLabel(self $value): string
{
return match ($value) {
self::ACTIVE => 'Active',
self::NOT_ACTIVE => 'Not active',
};
}
}
<?php
require_once 'UserStatus.php';
echo UserStatus::getLabel(UserStatus::ACTIVE); // Active
Enum constants
Enum may have constants, just like class. Enum constant may refer to an enum case as well.
<?php
enum UserStatus
{
case ACTIVE;
case NOT_ACTIVE;
public const DEFAULT = self::ACTIVE;
public const TOTAL_STATUSES = 2;
}
Enum properties is not allowed
Enum cannot contain properties. It is an important difference between enum and class.
<?php
enum UserStatus
{
private string $status; // Error
}
Enum and interfaces
Just like class, enum can implement interfaces.
<?php
interface HasLabelInterface
{
public function getLabel(): string;
}
<?php
enum UserStatus implements HasLabelInterface
{
case ACTIVE;
case NOT_ACTIVE;
public function getLabel(): string { return '...'; }
}
If you want to implement an interface in backed enum, after the enum name must come a type and after it implements
keyword.
<?php
enum UserStatus : string implements HasLabelInterface
{
case ACTIVE = 'A';
case NOT_ACTIVE = 'N';
public function getLabel(): string { return '...'; }
}
Enum name and value
Each case in enum has property name
which contains the name of the case. The name
property is read-only.
<?php
enum UserStatus
{
case ACTIVE;
case NOT_ACTIVE;
}
<?php
require_once 'UserStatus.php';
echo UserStatus::ACTIVE->name; // ACTIVE
In backed enum, each case also has property value
which is read-only as well.
<?php
enum UserStatus : string
{
case ACTIVE = 'A';
case NOT_ACTIVE = 'N';
}
<?php
require_once 'UserStatus.php';
echo UserStatus::ACTIVE->value; // A
Enum has cases
static method which allows retrieving all available cases of the enum.
<?php
require_once 'UserStatus.php';
foreach (UserStatus::cases() as $status) {
// ACTIVE A
// NOT_ACTIVE N
echo $status->name.' '.$status->value.PHP_EOL;
}
Enum as array keys is not allowed
It is not possible to use enum as array keys.
<?php
enum UserStatus : string
{
case ACTIVE = 'A';
case NOT_ACTIVE = 'N';
}
<?php
require_once 'UserStatus.php';
$statuses = [
UserStatus::ACTIVE => 'Active', // Error
UserStatus::NOT_ACTIVE => 'Not active', // Error
];
Enum properties in constant expressions
Since PHP 8.2, enum properties such as name
and value
can be used in constant expressions. The following code is valid since PHP 8.2:
<?php
enum UserStatus : string
{
case ACTIVE = 'A';
case NOT_ACTIVE = 'N';
public const LABELS = [
self::ACTIVE->value => 'Active', // Valid
self::NOT_ACTIVE->value => 'Not active', // Valid
];
}
Leave a Comment
Cancel reply