From 82ec4acb757679ddc164f7b27b1fc527b079cde3 Mon Sep 17 00:00:00 2001 From: Daniel Beardsley Date: Wed, 28 Oct 2020 15:29:33 -0700 Subject: [PATCH 1/3] __callStatic: cache created Enum instances Instead of creating a new one each time, cache them. This only matters if you're creating thousands of these objects. I've used a small test script: > + */ + protected static $instances = []; + /** * Creates a new value of some type * @@ -211,17 +219,19 @@ public static function search($value) * @param array $arguments * * @return static - * @psalm-pure * @throws \BadMethodCallException */ public static function __callStatic($name, $arguments) { - $array = static::toArray(); - if (isset($array[$name]) || \array_key_exists($name, $array)) { - return new static($array[$name]); + $class = static::class; + if (!isset(self::$instances[$class][$name])) { + $array = static::toArray(); + if (!isset($array[$name]) && !\array_key_exists($name, $array)) { + throw new \BadMethodCallException("No static method or enum constant '$name' in class " . static::class); + } + return self::$instances[$class][$name] = new static($array[$name]); } - - throw new \BadMethodCallException("No static method or enum constant '$name' in class " . static::class); + return self::$instances[$class][$name]; } /** From facf0bfcb5944e299259aebddf50f4eb4dcf053d Mon Sep 17 00:00:00 2001 From: Daniel Beardsley Date: Thu, 29 Oct 2020 09:34:42 -0700 Subject: [PATCH 2/3] Code formatting --- src/Enum.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Enum.php b/src/Enum.php index c6b6ffc..4b7b5fc 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -227,7 +227,8 @@ public static function __callStatic($name, $arguments) if (!isset(self::$instances[$class][$name])) { $array = static::toArray(); if (!isset($array[$name]) && !\array_key_exists($name, $array)) { - throw new \BadMethodCallException("No static method or enum constant '$name' in class " . static::class); + $message = "No static method or enum constant '$name' in class " . static::class; + throw new \BadMethodCallException($message); } return self::$instances[$class][$name] = new static($array[$name]); } From 14edb7bd4b5219d99c3a8bc4789eef96bd006739 Mon Sep 17 00:00:00 2001 From: Daniel Beardsley Date: Fri, 30 Oct 2020 13:09:24 -0700 Subject: [PATCH 3/3] Enum::CONST(): never return same instance Enums shouldn't be compared with ===, but static accessors are now cached so === was working. Let's return a clone each time so === won't be true for values retrieved from these accessors. Note: this actually had no impact on the performance gains from a few commits ago. --- src/Enum.php | 2 +- tests/EnumTest.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Enum.php b/src/Enum.php index 4b7b5fc..b8b9327 100644 --- a/src/Enum.php +++ b/src/Enum.php @@ -232,7 +232,7 @@ public static function __callStatic($name, $arguments) } return self::$instances[$class][$name] = new static($array[$name]); } - return self::$instances[$class][$name]; + return clone self::$instances[$class][$name]; } /** diff --git a/tests/EnumTest.php b/tests/EnumTest.php index 9fe9022..cb08d29 100755 --- a/tests/EnumTest.php +++ b/tests/EnumTest.php @@ -143,6 +143,7 @@ public function testStaticAccess() $this->assertEquals(new EnumFixture(EnumFixture::FOO), EnumFixture::FOO()); $this->assertEquals(new EnumFixture(EnumFixture::BAR), EnumFixture::BAR()); $this->assertEquals(new EnumFixture(EnumFixture::NUMBER), EnumFixture::NUMBER()); + $this->assertNotSame(EnumFixture::NUMBER(), EnumFixture::NUMBER()); } /**