Skip to content

Instantly share code, notes, and snippets.

@Cxarli
Created August 9, 2018 22:17
Show Gist options
  • Save Cxarli/c175a73240fa4b51f3c0990a6ba83301 to your computer and use it in GitHub Desktop.
Save Cxarli/c175a73240fa4b51f3c0990a6ba83301 to your computer and use it in GitHub Desktop.
Enum implementation in PHP
<?php
abstract class Enum {
private static $cache = [];
// Helper function to load the required fields into the cache.
private static function loadCache(): void {
// Create cache for enum
self::$cache[static::class] = [];
// Get all constants
$refl = new \ReflectionClass(static::class);
$consts = $refl->getConstants();
// Store constants in cache
// NOTE: The value of the constant is ignored
foreach (array_keys($consts) as $i => $key) {
self::$cache[static::class][$key] = new static($i, $key);
}
}
// Enum::A() should give Enum::$cache[Enum::A]
public static function __callStatic(string $name, $_): self {
// Make sure the cache is loaded
if (! isset(self::$cache[static::class])) {
static::loadCache();
}
// Check if key exists
if (! isset(self::$cache[static::class][$name])) {
throw new \Exception("Invalid key: '$name'");
return null;
}
// Return item from cache
return self::$cache[static::class][$name];
}
// Enum::from('A') should give Enum::$cache[Enum::A]
public static function from(string $key): self {
return static::$key();
}
private $val;
private $name;
private function __construct(int $val, string $name) {
$this->val = $val;
$this->name = $name;
}
public function __toString(): string {
return static::class . ' {' . $this->name . '}';
}
public function name(): string {
return $this->name;
}
public function val(): int {
return $this->val;
}
public function __debugInfo(): array {
return [
'name' => $this->name,
'val' => $this->val,
];
}
}
class Month extends Enum {
const January = null;
const February = null;
const March = null;
const April = null;
const May = null;
const June = null;
const July = null;
const August = null;
const September = null;
const October = null;
const November = null;
const December = null;
}
class Weekday extends Enum {
const Monday = null;
const Tuesday = null;
const Wednesday = null;
const Thursday = null;
const Friday = null;
const Saturday = null;
const Sunday = null;
}
function planDate(Month $month, Weekday $day) {
if ((
// month between january and april
Month::January()->val() <= $month->val()
&& $month->val() <= Month::April()->val()
) || (
// month between october and december
Month::October()->val() <= $month->val()
&& $month->val() <= Month::December()->val()
))
{
return "Sorry, but then it's too cold outside.";
}
if ($day == Weekday::Friday()) {
return "Sorry, I already have an important meeting.";
}
return "A " . $day->name() . " in " . $month->name() . " sounds nice!";
}
echo planDate(Month::March(), Weekday::Monday()) . "\n";
echo planDate(Month::from("August"), Weekday::Friday()) . "\n";
echo planDate(Month::from("June"), Weekday::from("Sunday")) . "\n";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment