Skip to content

Commit ea06934

Browse files
authored
Merge pull request #136 from drealecs/improve_getKey_performance
Improve getKey method performance
2 parents 9fcffe3 + be02f8d commit ea06934

File tree

2 files changed

+62
-10
lines changed

2 files changed

+62
-10
lines changed

src/Enum.php

+35-8
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ abstract class Enum implements \JsonSerializable
2828
*/
2929
protected $value;
3030

31+
/**
32+
* Enum key, the constant name
33+
*
34+
* @var string
35+
*/
36+
private $key;
37+
3138
/**
3239
* Store existing constants in a static cache per object.
3340
*
@@ -61,22 +68,29 @@ public function __construct($value)
6168
$value = $value->getValue();
6269
}
6370

64-
static::assertValidValue($value);
71+
$this->key = static::assertValidValueReturningKey($value);
6572

6673
/** @psalm-var T */
6774
$this->value = $value;
6875
}
6976

77+
public function __wakeup()
78+
{
79+
if ($this->key === null) {
80+
$this->key = static::search($this->value);
81+
}
82+
}
83+
7084
/**
7185
* @param mixed $value
7286
* @return static
7387
* @psalm-return static<T>
7488
*/
7589
public static function from($value): self
7690
{
77-
static::assertValidValue($value);
91+
$key = static::assertValidValueReturningKey($value);
7892

79-
return new static($value);
93+
return self::__callStatic($key, []);
8094
}
8195

8296
/**
@@ -93,11 +107,11 @@ public function getValue()
93107
* Returns the enum key (i.e. the constant name).
94108
*
95109
* @psalm-pure
96-
* @return mixed
110+
* @return string
97111
*/
98112
public function getKey()
99113
{
100-
return static::search($this->value);
114+
return $this->key;
101115
}
102116

103117
/**
@@ -201,9 +215,22 @@ public static function isValid($value)
201215
*/
202216
public static function assertValidValue($value): void
203217
{
204-
if (!static::isValid($value)) {
218+
self::assertValidValueReturningKey($value);
219+
}
220+
221+
/**
222+
* Asserts valid enum value
223+
*
224+
* @psalm-pure
225+
* @psalm-assert T $value
226+
*/
227+
private static function assertValidValueReturningKey($value): string
228+
{
229+
if (false === ($key = static::search($value))) {
205230
throw new \UnexpectedValueException("Value '$value' is not part of the enum " . static::class);
206231
}
232+
233+
return $key;
207234
}
208235

209236
/**
@@ -224,11 +251,11 @@ public static function isValidKey($key)
224251
/**
225252
* Return key for value
226253
*
227-
* @param $value
254+
* @param mixed $value
228255
*
229256
* @psalm-param mixed $value
230257
* @psalm-pure
231-
* @return mixed
258+
* @return string|false
232259
*/
233260
public static function search($value)
234261
{

tests/EnumTest.php

+27-2
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ public function testFailToCreateEnumWithInvalidValueThroughNamedConstructor($val
6060
EnumFixture::from($value);
6161
}
6262

63+
public function testFailToCreateEnumWithEnumItselfThroughNamedConstructor(): void
64+
{
65+
$this->expectException(\UnexpectedValueException::class);
66+
$this->expectExceptionMessage("Value 'foo' is not part of the enum " . EnumFixture::class);
67+
68+
EnumFixture::from(EnumFixture::FOO());
69+
}
70+
6371
/**
6472
* Contains values not existing in EnumFixture
6573
* @return array
@@ -316,12 +324,13 @@ public function testSerialize()
316324
{
317325
// split string for Pretty CI: "Line exceeds 120 characters"
318326
$bin = '4f3a33303a224d79434c6162735c54657374735c456e756d5c456e756d4669787'.
319-
'4757265223a313a7b733a383a22002a0076616c7565223b733a333a22666f6f223b7d';
327+
'4757265223a323a7b733a383a22002a0076616c7565223b733a333a22666f6f223b73'.
328+
'3a32323a22004d79434c6162735c456e756d5c456e756d006b6579223b733a333a22464f4f223b7d';
320329

321330
$this->assertEquals($bin, bin2hex(serialize(EnumFixture::FOO())));
322331
}
323332

324-
public function testUnserialize()
333+
public function testUnserializeVersionWithoutKey()
325334
{
326335
// split string for Pretty CI: "Line exceeds 120 characters"
327336
$bin = '4f3a33303a224d79434c6162735c54657374735c456e756d5c456e756d4669787'.
@@ -332,6 +341,22 @@ public function testUnserialize()
332341

333342
$this->assertEquals(EnumFixture::FOO, $value->getValue());
334343
$this->assertTrue(EnumFixture::FOO()->equals($value));
344+
$this->assertTrue(EnumFixture::FOO() == $value);
345+
}
346+
347+
public function testUnserialize()
348+
{
349+
// split string for Pretty CI: "Line exceeds 120 characters"
350+
$bin = '4f3a33303a224d79434c6162735c54657374735c456e756d5c456e756d4669787'.
351+
'4757265223a323a7b733a383a22002a0076616c7565223b733a333a22666f6f223b73'.
352+
'3a32323a22004d79434c6162735c456e756d5c456e756d006b6579223b733a333a22464f4f223b7d';
353+
354+
/* @var $value EnumFixture */
355+
$value = unserialize(pack('H*', $bin));
356+
357+
$this->assertEquals(EnumFixture::FOO, $value->getValue());
358+
$this->assertTrue(EnumFixture::FOO()->equals($value));
359+
$this->assertTrue(EnumFixture::FOO() == $value);
335360
}
336361

337362
/**

0 commit comments

Comments
 (0)