The basic syntax looks like this:
enum TransportMode {
case Bicycle;
case Car;
case Ship;
case Plane;
case Feet;
}
function travelCost(TransportMode $mode, int $distance): int
{ /* implementation */ }
$mode = TransportMode::Boat;
$bikeCost = travelCost(TransportMode::Bicycle, 90);
$boatCost = travelCost($mode, 90);
// this one would fail: (Enums are singletons, not scalars)
$failCost = travelCost('Car', 90);
Values
By default, enumerations are not backed by any kind of scalar. So TransportMode::Bicycle
is not 0
, and you cannot compare using >
or <
between enumerations.
But the following works:
$foo = TransportMode::Car;
$bar = TransportMode::Car;
$baz = TransportMode::Bicycle;
$foo === $bar; // true
$bar === $baz; // false
$foo instanceof TransportMode; // true
$foo > $bar || $foo < $bar; // false either way
Backed Enumerations
You can also have "backed" enums, where each enumeration case is "backed" by either an int
or a string
.
enum Metal: int {
case Gold = 1932;
case Silver = 1049;
case Lead = 1134;
case Uranium = 1905;
case Copper = 894;
}
- If one case has a backed value, all cases need to have a backed value, there are no auto-generated values.
- Notice the type of the backed value is declared right after the enumeration name
- Backed values are read only
- Scalar values need to be unique
- Values need to be literals or literal expressions
- To read the backed value you access the
value
property: Metal::Gold->value
.
Finally, backed enumerations implement a BackedEnum
interface internally, which exposes two methods:
from(int|string): self
tryFrom(int|string): ?self
They are almost equivalent, with the important distinction that the first one will throw an exception if the value is not found, and the second will simply return null
.
// usage example:
$metal_1 = Metal::tryFrom(1932); // $metal_1 === Metal::Gold;
$metal_2 = Metal::tryFrom(1000); // $metal_2 === null;
$metal_3 = Metal::from(9999); // throws Exception
Methods
Enumerations may have methods, and thus implement interfaces.
interface TravelCapable
{
public function travelCost(int $distance): int;
public function requiresFuel(): bool;
}
enum TransportMode: int implements TravelCapable{
case Bicycle = 10;
case Car = 1000 ;
case Ship = 800 ;
case Plane = 2000;
case Feet = 5;
public function travelCost(int $distance): int
{
return $this->value * $distance;
}
public function requiresFuel(): bool {
return match($this) {
TransportMode::Car, TransportMode::Ship, TransportMode::Plane => true,
TransportMode::Bicycle, TransportMode::Feet => false
}
}
}
$mode = TransportMode::Car;
$carConsumesFuel = $mode->requiresFuel(); // true
$carTravelCost = $mode->travelCost(800); // 800000
Value listing
Both Pure Enums and Backed Enums internally implement the interface UnitEnum
, which includes the (static) method UnitEnum::cases()
, and allows to retrieve an array of the cases defined in the enumeration:
$modes = TransportMode::cases();
And now $modes
is:
[
TransportMode::Bicycle,
TransportMode::Car,
TransportMode::Ship,
TransportMode::Plane
TransportMode::Feet
]
Static methods
Enumerations can implement their own static
methods, which would generally be used for specialized constructors.
This covers the basics. To get the whole thing, head on to the relevant RFC until the feature is released and published in PHP's documentation.
8.1
expected to be released in November 2021. It looks like the following:enum Status { case started; case stopped; case paused; }
– Mclaren