I know that PHP doesn\'t have native Enumerations. But I have become accustomed to them from the Java world. I would love to use enums as a way to give predefined values whi
One of the aspects missing from some of the other answers here is a way to use enums with type hinting.
If you define your enum as a set of constants in an abstract class, e.g.
abstract class ShirtSize {
public const SMALL = 1;
public const MEDIUM = 2;
public const LARGE = 3;
}
then you can't type hint it in a function parameter - for one, because it's not instantiable, but also because the type of ShirtSize::SMALL
is int
, not ShirtSize
.
That's why native enums in PHP would be so much better than anything we can come up with. However, we can approximate an enum by keeping a private property which represents the value of the enum, and then restricting the initialization of this property to our predefined constants. To prevent the enum from being instantiated arbitrarily (without the overhead of type-checking a whitelist), we make the constructor private.
class ShirtSize {
private $size;
private function __construct ($size) {
$this->size = $size;
}
public function equals (ShirtSize $s) {
return $this->size === $s->size;
}
public static function SMALL () { return new self(1); }
public static function MEDIUM () { return new self(2); }
public static function LARGE () { return new self(3); }
}
Then we can use ShirtSize
like this:
function sizeIsAvailable ($productId, ShirtSize $size) {
// business magic
}
if(sizeIsAvailable($_GET["id"], ShirtSize::LARGE())) {
echo "Available";
} else {
echo "Out of stock.";
}
$s2 = ShirtSize::SMALL();
$s3 = ShirtSize::MEDIUM();
echo $s2->equals($s3) ? "SMALL == MEDIUM" : "SMALL != MEDIUM";
This way, the biggest difference from the user's perspective is that you have to tack on a ()
on the constant's name.
One downside though is that ===
(which compares object equality) will return false when ==
returns true. For that reason, it's best to provide an equals
method, so that users don't have to remember to use ==
and not ===
to compare two enum values.
EDIT: A couple of the existing answers are very similar, particularly: https://stackoverflow.com/a/25526473/2407870.