Тип даних Enum об'єкту в PHP

29. 05. 2022

Obsah článku

Починаючи з версії PHP 8.1, тип даних Enum можна використовувати для визначення точних значень перерахування для списку. Це корисно у випадках, коли ми знаємо, що значення змінної може приймати лише декілька конкретних значень.

Наприклад, так я зберігаю типи повідомлень:

enum OrderNotificationType: string
{
case Email = 'електронна пошта';
case Sms = 'текст';
}

У мові PHP тип даних Enum є класичним об'єктом, який поводиться як спеціальний тип константи, але також має екземпляр, який можна передавати. Однак, на відміну від звичайного об'єкта, на нього поширюється низка обмежень.

Відмінності між Enum та об'єктами

Хоча зчислення побудовані поверх класів та об'єктів, вони не підтримують всю функціональність, пов'язану з об'єктами. Зокрема, перечислювальним об'єктам заборонено мати внутрішній стан (вони завжди повинні бути статичним класом).

Конкретний перелік відмінностей:

  • Будівельники і руйнівники заборонені.
  • Спадкування не підтримується. Зчислення не можуть бути розширені або успадковані іншим класом.
  • Не допускаються статичні або об'єктні властивості.
  • Клонування конкретних значень (екземплярів) Enum не підтримується, кожен окремий екземпляр повинен бути одиничним екземпляром.
  • Магічні методи, крім зазначених нижче, заборонені.

Наступні функції об'єкта доступні і поводяться так само, як і будь-який інший об'єкт:

  • Публічні, приватні та захищені методи.
  • Загальнодоступні, приватні та захищені статичні методи.
  • Публічні, приватні та захищені константи.
  • Зчислення можуть реалізовувати будь-яку кількість інтерфейсів.
  • Атрибути можуть бути прикріплені до переліків та випадків. Цільовий фільтр TARGET_CLASS включає в себе самі переліки. Цільовий фільтр TARGET_CLASS_CONST включає в себе випадки Enum.
  • Магічні методи __call, __callStatic та __invoke.
  • Константи __КЛАС__ та __ФУНКЦІЯ__ поводять себе як звичайні константи
  • Магічна константа ::class на типі Enum оцінюється як повне ім'я типу даних, включаючи будь-який простір імен, точно як для об'єкту. Магічна константа ::class на екземплярі типу Case також обчислюється як тип Enum, оскільки він є екземпляром іншого типу.

Використання Enum як типу даних

Уявіть собі, що у нас є перерахування, яке представляє типи позовів. У цьому випадку нам потрібно лише визначити тип Suit і зберігати окремі допустимі значення.

Потім ми отримуємо екземпляр конкретної опції класично через квадратик, як при роботі зі статичною константою.

Приклад опису зчислення Enum, виклику його за конкретним типом та передачі у функцію:

enum Suit
{
case Hearts;
case Diamonds;
case Clubs;
case Spades;
}
function doStuff(Suit $s)
{
// ...
}
doStuff(Suit::Spades);

Порівняння двох величин

Принципова перевага перечислень над об'єктами та константами полягає в тому, що легко порівнювати їх значення.

Базове порівняння, що ми працюємо з конкретною величиною, можна зробити наступним чином:

$a = Suit::Spades;
$b = Suit::Spades;
$a === $b; // true

Дуже часто нам також потрібно вирішити, що певне значення належить до допустимого перерахування значень Enum. Це можна легко перевірити наступним чином:

$a = Suit::Spades;
$a instanceof Suit; // true

Читання значення типу

Ми можемо прочитати значення конкретного типу або як ім'я викликаючої константи, або безпосередньо як реальне визначене значення (якщо воно існує):

enum Colors
{
case Red;
case Blue;
case Green;
public function getColor(): string
{
return $this->name;
}
}
function paintColor(Colors $colors): void
{
echo "Фарба:" . $colors->getColor();
}

Значення викликаючої константи зчитується через властивість name. Важливо також, що безпосередньо в типі даних Enum може бути реалізована користувацька функція, яку можна викликати над кожним Enum.

Якщо конкретний Enum реалізує також і дійсні значення (які приховані під кожною константою), то їх значення також можна прочитати:

enum OrderNotificationType: string
{
case Email = 'електронна пошта';
case Sms = 'текст';
}
$type = OrderNotificationType::Email;
echo $type->value;

Всі допустимі значення Enum

Часто нам потрібно перерахувати (наприклад, користувачеві в повідомленні про помилку) всі можливі значення, які може приймати Enum. При використанні констант це було неможливо, Enum дозволяє це легко зробити:

Suit::cases();

Повертає [масть::Черва, масть::Бубна, масть::Трефа, масть::Піка].

Переконатись, що змінна має тип Enum

Ми можемо легко перевірити, що певна невідома змінна містить перерахування за умовою:

if ($haystack instanceof \BackedEnum) {

Кожен об'єкт Enum автоматично є нащадком узагальненого інтерфейсу \BackedEnum.

Більш детальну інформацію можна знайти в обговоренні на GitHub PhpStan: https://github.com/phpstan/phpstan/issues/7304

Jan Barášek   Více o autorovi

Autor článku pracuje jako seniorní vývojář a software architekt v Praze. Navrhuje a spravuje velké webové aplikace, které znáte a používáte. Od roku 2009 nabral bohaté zkušenosti, které tímto webem předává dál.

Rád vám pomůžu:

Související články

1.
2.