fromName для enum



Перечисления (енамы) бывают двух типов: чистые и грязные типизированные, со скалярным эквивалентом. Типизированные енамы реализуют интерфейс BackedEnum с дополнительными методами from и tryFrom — они позволяют получить перечисление по его скалярному эквиваленту ($value).



В этом посте мы попробуем добавить аналогичные методы fromName и tryFromName для получения перечисления любого типа по его имени ($name).



Для начала обратим внимание на любопытную фразу в документации: "Для вариантов перечисления применяются те же правила синтаксиса, что и для любой метки в PHP, смотрите Константы". По идее, это означает, что мы можем без рефлексии динамически работать с енамами как с константами. Попробуем!



enum Locale

{

case ru;

case en;



public static function tryFromName(string $name): ?self

{

$constant = self::class.'::'.$name;



if (\defined($constant)) {

return \constant($constant);

}



return null;

}



public static function fromName(string $name): self

{

return self::tryFromName($name)

?? throw new \ValueError(sprintf(

'"%s" is not a valid name for enum "%s"',

$name,

self::class,

));

}

}



Вуаля, работает! https://3v4l.org/EgBB1



Обратите внимание на комментарии @SerafimArts про нюансы использования констант и решение задачи через рефлексию.



P.S.: Задача этого поста — поиграться с перечислениями, чтобы лучше их прочувствовать. Я не призываю так делать. Если при работе с чистым енамом выясняется, что его нужно получать по имени, то лучше поменять такой енам на типизированный и использовать встроенные методы from и tryFrom.