Тип даних Enum об'єкту в PHP
Починаючи з версії PHP 8.1, тип даних Enum можна використовувати для визначення точних значень перерахування для списку. Це корисно у випадках, коли ми знаємо, що значення змінної може приймати лише декілька конкретних значень.
Наприклад, так я зберігаю типи повідомлень:
enum OrderNotificationType: string{case Email = 'електронна пошта';case Sms = 'текст';}
У мові PHP тип даних Enum є класичним об'єктом, який поводиться як спеціальний тип константи, але також має екземпляр, який можна передавати. Oднак, на відміну від звичайного об'єкта, на нього поширюється низка обмежень.
Відмінності між Enum та об'єктами
Хоча зчислення побудовані поверх класів та об'єктів, вони не підтримують всю функціональність, пов'язану з об'єктами. Зокрема, перечислювальним об'єктам заборонено мати внутрішній стан (вони завжди повинні бути статичним класом).
Конкретний перелік відмінностей:
- Будівельники і руйнівники заборонені.
- Спадкування не підтримується. Зчислення не можуть бути розширені або успадковані іншим класом.
- Не допускаються статичні або об'єктні властивості.
- Клонування конкретних значень (екземплярів) Enum не підтримується, кожен окремий екземпляр повинен бути одиничним екземпляром.
- Магічні методи, крім зазначених нижче, заборонені.
Наступні функції об'єкта доступні і поводяться так само, як і будь-який інший об'єкт:
- Публічні, приватні та захищені методи.
- Загальнодоступні, приватні та захищені статичні методи.
- Публічні, приватні та захищені константи.
- Зчислення можуть реалізовувати будь-яку кількість інтерфейсів.
- Aтрибути можуть бути прикріплені до переліків та випадків. Цільовий фільтр
TARGET_CLASSвключає в себе самі переліки. Цільовий фільтрTARGET_CLASS_CONSTвключає в себе випадки Enum. - Магічні методи
__call,__callStaticта__invoke. - Константи
__КЛAС__та__ФУНКЦІЯ__поводять себе як звичайні константи - Магічна константа
::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