Skip to content

Instantly share code, notes, and snippets.

@ostrolucky
Created June 22, 2017 17:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ostrolucky/4614b062ffc2156d607fca899eea8a89 to your computer and use it in GitHub Desktop.
Save ostrolucky/4614b062ffc2156d607fca899eea8a89 to your computer and use it in GitHub Desktop.
PHP enum class by LtAramaki
<?php
abstract class Enum {
private $name;
private static $enums;
private function __construct($name) {
$this->name = $name;
}
/**
* Returns an assoc. array of ['ENUM_NAME' => $ENUM_VALUE] for all enum values.
* @return array
*/
public static function getAll(): array {
$class = static::class;
if (!isset(self::$enums[$class])) static::init();
return self::$enums[$class];
}
/**
* Return an enum value (object) from a string name.
* @return $this
*/
public static function fromString($name) {
return static::__callStatic($name, []);
}
public function __toString() {
return $this->name;
}
public static function __callStatic($name, $args) {
$class = static::class;
if (!isset(self::$enums[$class])) static::init();
if (!isset(self::$enums[$class][$name])) {
throw new \TypeError('Undefined enum ' . $class . '::' . $name . '()');
}
return self::$enums[$class][$name];
}
private static function init() {
$class = static::class;
if ($class === __CLASS__) {
throw new \Exception('Do not invoke methods directly on class Enum.');
}
$doc = (new \ReflectionClass($class))->getDocComment();
if (preg_match_all('/@method\s+static\s+(\w+)/i', $doc, $matches)) {
foreach ($matches[1] as $name) {
self::$enums[$class][$name] = new static($name);
}
} else {
throw new \Exception('Please provide a PHPDoc for ' . $class . ' with a static @method for each enum value.');
}
}
}
/**
* @method static RED()
* @method static GREEN()
* @method static BLUE()
*/
class Color extends Enum {}
$red = Color::RED();
$red2 = Color::RED();
$green = Color::GREEN();
var_dump($red === $red2);
var_dump($red == $red2);
var_dump($red === $green);
var_dump($red == $green);
var_dump((string) $red);
var_dump((string) $green);
var_dump($red === Color::fromString('RED'));
var_dump(Color::getAll());
try {
$geern = Color::GEERN(); // Intentional typo. Throws.
} catch (\Throwable $e) {
echo get_class($e) . ': ' . $e->getMessage(). "\n";
}
try {
Enum::getAll(); // Shouldn't call methods directly on Enum. Throws.
} catch (\Throwable $e) {
echo get_class($e) . ': ' . $e->getMessage(). "\n";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment