3v4l.org

run code in 300+ PHP versions simultaneously
<?php namespace MabeEnum; use ReflectionClass; use InvalidArgumentException; use LogicException; abstract class Enum { /** * The selected value * * @var null|boolean|int|float|string */ private $value; /** * The ordinal number of the value * * @var null|int */ private $ordinal; /** * An array of available constants by class * * @var array ["$class" => ["$const" => $value, ...], ...] */ private static $constants = array(); /** * Already instantiated enums * * @var array ["$class" => ["$const" => $instance, ...], ...] */ private static $instances = array(); /** * Constructor * * @param null|boolean|int|float|string $value The value to select * @param int|null $ordinal The ordinal number of the value */ final private function __construct($value, $ordinal = null) { $this->value = $value; $this->ordinal = $ordinal; } /** * Get the current selected constant name * * @return string * @see getName() */ public function __toString() { return $this->getName(); } /** * @throws LogicException Enums are not cloneable * because instances are implemented as singletons */ final private function __clone() { throw new LogicException('Enums are not cloneable'); } /** * @throws LogicException Enums are not serializable * because instances are implemented as singletons */ final public function __sleep() { throw new LogicException('Enums are not serializable'); } /** * @throws LogicException Enums are not serializable * because instances are implemented as singletons */ final public function __wakeup() { throw new LogicException('Enums are not serializable'); } /** * Get the current selected value * * @return null|boolean|int|float|string */ final public function getValue() { return $this->value; } /** * Get the current selected constant name * * @return string */ final public function getName() { return array_search($this->value, self::detectConstants(get_called_class()), true); } /** * Get the ordinal number of the selected value * * @return int */ final public function getOrdinal() { if ($this->ordinal !== null) { return $this->ordinal; } // detect ordinal $ordinal = 0; $value = $this->value; foreach (self::detectConstants(get_called_class()) as $constValue) { if ($value === $constValue) { break; } ++$ordinal; } $this->ordinal = $ordinal; return $ordinal; } /** * Compare this enum against another enum and check if it's the same value * * @param mixed $value * @return boolean */ final public function is($enum) { return $this->value === $enum || (($enum instanceof static || $this instanceof $enum) && $this->value === $enum->getValue()); } /** * Get an enum of the given value * * @param static|null|boolean|int|float|string $value * @return static * @throws InvalidArgumentException On an unknwon or invalid value * @throws LogicException On ambiguous constant values */ final public static function get($value) { if ($value instanceof static) { $value = $value->getValue(); } $class = get_called_class(); $constants = self::detectConstants($class); $name = array_search($value, $constants, true); if ($name === false) { if (is_scalar($value)) { throw new InvalidArgumentException('Unknown value ' . var_export($value, true)); } else { throw new InvalidArgumentException('Invalid value of type ' . gettype($value)); } } if (isset(self::$instances[$class][$name])) { return self::$instances[$class][$name]; } return self::$instances[$class][$name] = new $class($constants[$name]); } /** * Get an enum by the given name * * @param string $name The name to instantiate the enum by * @return static * @throws InvalidArgumentException On an invalid or unknown name * @throws LogicException On ambiguous constant values */ final public static function getByName($name) { $name = (string) $name; $class = get_called_class(); if (isset(self::$instances[$class][$name])) { return self::$instances[$class][$name]; } $const = $class . '::' . $name; if (!defined($const)) { throw new InvalidArgumentException($const . ' not defined'); } return self::$instances[$class][$name] = new $class(constant($const)); } /** * Get an enum by the given ordinal number * * @param int $ordinal The ordinal number to instantiate the enum by * @return static * @throws InvalidArgumentException On an invalid ordinal number * @throws LogicException On ambiguous constant values */ final public static function getByOrdinal($ordinal) { $ordinal = (int) $ordinal; $class = get_called_class(); $constants = self::detectConstants($class); $item = array_slice($constants, $ordinal, 1, false); if (!$item) { throw new InvalidArgumentException(sprintf( 'Invalid ordinal number, must between 0 and %s', count($constants) - 1 )); } $name = key($item); if (isset(self::$instances[$class][$name])) { return self::$instances[$class][$name]; } return self::$instances[$class][$name] = new $class(current($item), $ordinal); } /** * Clears all instantiated enums * * NOTE: This can break singleton behavior ... use it with caution! * * @return void */ final public static function clear() { $class = get_called_class(); unset(self::$instances[$class], self::$constants[$class]); } /** * Get all available constants of the called class * * @return array * @throws LogicException On ambiguous constant values */ final public static function getConstants() { return self::detectConstants(get_called_class()); } /** * Detect constants available by given class * * @param string $class * @return array * @throws LogicException On ambiguous constant values */ private static function detectConstants($class) { var_dump(get_called_class()); if (!isset(self::$constants[$class])) { $reflection = new ReflectionClass($class); $constants = $reflection->getConstants(); // values needs to be unique $ambiguous = array(); foreach ($constants as $value) { $names = array_keys($constants, $value, true); if (count($names) > 1) { $ambiguous[var_export($value, true)] = $names; } } if ($ambiguous) { throw new LogicException( 'All possible values needs to be unique. The following are ambiguous: ' . implode(', ', array_map(function ($names) use ($constants) { return implode('/', $names) . '=' . var_export($constants[$names[0]], true); }, $ambiguous)) ); } // This is required to make sure that constants of base classes will be the first while (($reflection = $reflection->getParentClass()) && $reflection->name !== __CLASS__) { $constants = $reflection->getConstants() + $constants; } self::$constants[$class] = $constants; } return self::$constants[$class]; } /** * Instantiate an enum by a name of a constant. * * This will be called automatically on calling a method * with the same name of a defined constant. * * @param string $method The name to instantiate the enum by (called as method) * @param array $args There should be no arguments * @return static * @throws InvalidArgumentException On an invalid or unknown name * @throws LogicException On ambiguous constant values */ final public static function __callStatic($method, array $args) { return self::getByName($method); } } class TestEnum1 extends Enum { const TEST1 = 'TEST1'; } class TestEnum2 extends TestEnum1 { const TEST2 = 'TEST2'; } $test1 = TestEnum1::TEST1(); $test2 = TestEnum2::TEST2();

Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).

VersionSystem time (s)User time (s)Memory (MiB)
8.3.60.0040.01118.55
8.3.50.0120.00618.15
8.3.40.0070.00718.79
8.3.30.0040.01119.13
8.3.20.0060.00320.33
8.3.10.0000.00920.65
8.3.00.0030.00619.38
8.2.180.0070.01116.50
8.2.170.0060.00922.96
8.2.160.0090.00620.60
8.2.150.0040.00424.18
8.2.140.0040.00424.66
8.2.130.0000.00826.16
8.2.120.0080.00022.24
8.2.110.0090.00021.99
8.2.100.0000.01217.91
8.2.90.0050.00318.00
8.2.80.0060.00319.04
8.2.70.0080.00017.75
8.2.60.0000.00918.29
8.2.50.0000.00818.29
8.2.40.0050.00317.75
8.2.30.0070.00417.90
8.2.20.0030.00517.89
8.2.10.0050.00318.11
8.2.00.0040.00417.84
8.1.270.0050.00322.14
8.1.260.0040.00426.35
8.1.250.0040.00428.09
8.1.240.0130.00022.23
8.1.230.0120.00020.88
8.1.220.0040.00417.74
8.1.210.0040.00418.77
8.1.200.0000.00817.47
8.1.190.0040.00417.35
8.1.180.0100.00018.10
8.1.170.0050.00317.62
8.1.160.0030.00519.11
8.1.150.0000.00818.61
8.1.140.0030.00517.55
8.1.130.0050.00318.03
8.1.120.0040.00417.46
8.1.110.0000.00917.60
8.1.100.0000.00717.57
8.1.90.0060.00317.56
8.1.80.0040.00417.55
8.1.70.0000.00817.47
8.1.60.0060.00317.75
8.1.50.0030.00517.57
8.1.40.0060.00317.60
8.1.30.0050.00317.65
8.1.20.0040.00417.76
8.1.10.0030.00617.75
8.1.00.0040.00417.46
8.0.300.0000.00918.77
8.0.290.0040.00416.75
8.0.280.0030.00318.57
8.0.270.0040.00417.25
8.0.260.0030.00517.23
8.0.250.0030.00317.13
8.0.240.0030.00517.13
8.0.230.0000.00717.17
8.0.220.0040.00417.05
8.0.210.0000.00717.04
8.0.200.0070.00017.16
8.0.190.0030.00617.10
8.0.180.0040.00416.91
8.0.170.0060.00316.98
8.0.160.0070.00017.05
8.0.150.0070.00017.07
8.0.140.0080.00016.99
8.0.130.0000.00613.46
8.0.120.0000.00816.92
8.0.110.0030.00517.01
8.0.100.0070.00017.06
8.0.90.0000.00816.89
8.0.80.0060.01016.97
8.0.70.0040.00417.01
8.0.60.0050.00316.95
8.0.50.0040.00417.08
8.0.30.0090.01117.07
8.0.20.0120.00717.42
8.0.10.0050.00217.14
8.0.00.0080.01316.82
7.4.330.0000.00615.00
7.4.320.0060.00016.56
7.4.300.0060.00016.54
7.4.290.0050.00316.73
7.4.280.0000.00916.60
7.4.270.0000.00716.71
7.4.260.0000.01016.60
7.4.250.0050.00216.56
7.4.240.0060.00116.57
7.4.230.0000.00716.52
7.4.220.0110.00816.66
7.4.210.0080.00816.64
7.4.200.0080.00016.41
7.4.160.0100.00716.46
7.4.150.0130.00617.40
7.4.140.0070.01217.86
7.4.130.0110.00816.67
7.4.120.0060.01216.65
7.4.110.0090.00916.60
7.4.100.0110.00616.52
7.4.90.0090.00916.57
7.4.80.0100.01019.39
7.4.70.0200.00316.61
7.4.60.0110.00616.71
7.4.50.0050.00516.72
7.4.40.0110.00716.66
7.4.30.0030.01716.60
7.4.00.0040.01514.91
7.3.330.0000.00513.37
7.3.320.0050.00013.33
7.3.310.0000.00716.28
7.3.300.0000.00616.45
7.3.290.0140.00016.55
7.3.280.0060.01016.50
7.3.270.0090.00917.40
7.3.260.0170.00316.45
7.3.250.0100.00916.62
7.3.240.0090.00916.50
7.3.230.0160.00316.45
7.3.210.0060.01216.43
7.3.200.0120.00619.39
7.3.190.0090.01316.48
7.3.180.0030.01916.60
7.3.170.0070.01016.38
7.3.160.0060.01216.48
7.2.330.0070.01016.93
7.2.320.0090.00916.95
7.2.310.0090.00916.90
7.2.300.0130.00316.95
7.2.290.0000.01616.92
7.1.100.0000.01118.32
7.1.70.0060.00616.97
7.1.60.0160.00919.61
7.1.50.0230.01334.47
7.1.00.0100.07022.30
7.0.200.0030.00716.69
7.0.140.0100.07021.97
7.0.100.0130.07321.76
7.0.90.0130.07721.69
7.0.80.0100.07021.80
7.0.70.0070.03721.73
7.0.60.0000.05321.71
7.0.50.0070.03722.05
7.0.40.0030.06320.15
7.0.30.0070.05720.15
7.0.20.0130.07020.18
7.0.10.0000.04320.07
7.0.00.0070.03719.95
5.6.280.0030.07721.20
5.6.250.0070.07720.87
5.6.240.0070.05020.57
5.6.230.0070.08320.83
5.6.220.0000.05320.76
5.6.210.0030.06720.62
5.6.200.0070.07321.04
5.6.190.0000.04321.24
5.6.180.0030.05321.09
5.6.170.0070.04021.03
5.6.160.0030.07021.12
5.6.150.0100.07721.09
5.6.140.0000.05321.10
5.6.130.0030.04021.18
5.6.120.0030.09021.03
5.6.110.0100.03321.11
5.6.100.0130.06721.09
5.6.90.0030.05021.19
5.6.80.0200.06720.56
5.6.70.0070.07320.47
5.6.60.0070.07720.46
5.6.50.0070.07720.39
5.6.40.0000.04020.51
5.6.30.0000.04020.36
5.6.20.0030.04020.51
5.6.10.0070.05320.38
5.6.00.0000.08020.49
5.5.380.0170.06720.40
5.5.370.0030.08020.62
5.5.360.0000.08320.55
5.5.350.0100.07720.38
5.5.340.0000.04320.91
5.5.330.0030.08320.96
5.5.320.0000.05020.98
5.5.310.0130.05320.96
5.5.300.0070.07320.88
5.5.290.0130.06720.96
5.5.280.0000.09320.96
5.5.270.0070.04720.86
5.5.260.0030.04020.99
5.5.250.0100.06020.66
5.5.240.0070.06320.27
5.5.230.0030.04020.36
5.5.220.0030.07720.33
5.5.210.0030.07320.31
5.5.200.0000.08320.33
5.5.190.0070.08020.20
5.5.180.0070.07020.28
5.5.160.0030.08020.30
5.5.150.0000.04020.18
5.5.140.0030.05320.30
5.5.130.0000.04020.17
5.5.120.0100.04020.24
5.5.110.0000.05020.21
5.5.100.0000.04320.15
5.5.90.0070.05020.11
5.5.80.0100.06720.16
5.5.70.0000.05320.19
5.5.60.0070.07320.07
5.5.50.0030.06720.07
5.5.40.0000.04020.09
5.5.30.0000.04320.16
5.5.20.0000.04020.21
5.5.10.0000.04720.13
5.5.00.0030.06720.13
5.4.450.0070.06319.45
5.4.440.0100.07019.56
5.4.430.0130.07319.19
5.4.420.0030.08019.18
5.4.410.0030.07019.10
5.4.400.0000.06719.13
5.4.390.0100.07019.03
5.4.380.0100.07019.04
5.4.370.0100.07019.14
5.4.360.0070.03319.18
5.4.350.0070.07719.24
5.4.340.0000.08018.89
5.4.320.0200.05719.12
5.4.310.0000.04019.18
5.4.300.0100.06718.96
5.4.290.0000.04719.04
5.4.280.0030.06719.12
5.4.270.0030.03719.20
5.4.260.0030.07318.89
5.4.250.0030.07319.05
5.4.240.0070.09319.13
5.4.230.0000.08018.95
5.4.220.0000.05719.25
5.4.210.0130.05719.13
5.4.200.0070.06019.11
5.4.190.0070.03319.15
5.4.180.0070.07318.89
5.4.170.0030.03719.13
5.4.160.0100.06319.22
5.4.150.0030.06719.11
5.4.140.0000.07716.46
5.4.130.0100.06716.40
5.4.120.0000.03716.45
5.4.110.0070.06716.38
5.4.100.0030.07016.33
5.4.90.0070.07016.42
5.4.80.0130.05716.47
5.4.70.0070.05716.43
5.4.60.0030.06716.43
5.4.50.0030.07016.48
5.4.40.0070.04316.38
5.4.30.0070.03016.50
5.4.20.0100.06016.41
5.4.10.0070.07316.41
5.4.00.0130.06315.82

preferences:
58.62 ms | 400 KiB | 5 Q