Перечисления (PHP 8.1)
Часть раздела Объектно-ориентированное программирование путешествия по PHP на Coddy — урок 59 из 91.
До PHP 8.1 представление фиксированного набора значений, таких как статусы или типы, означало использование констант классов или «магических» строк — оба этих подхода подвержены ошибкам. Enums (перечисления) предоставляют правильный способ определения типа, который может принимать только определенные, заранее заданные значения.
Определите перечисление с помощью ключевого слова enum:
<?php
enum Status {
case Pending;
case Active;
case Completed;
}
$status = Status::Active;
echo $status->name;
Вывод:
ActiveПеречисления (Enums) также могут иметь типизированные значения (backed values) — строковые или целочисленные значения, связанные с каждым вариантом. Это полезно при хранении перечислений в базах данных или API:
<?php
enum Status: string {
case Pending = 'pending';
case Active = 'active';
case Completed = 'completed';
}
$status = Status::Active;
echo $status->value;
Вывод:
activeТипизированные перечисления (backed enums) предоставляют метод from() для создания перечисления из его значения, а также метод tryFrom(), который возвращает null вместо того, чтобы выбрасывать ошибку при передаче недопустимых значений:
<?php
$status = Status::from('active'); // Возвращает Status::Active
$invalid = Status::tryFrom('unknown'); // Возвращает null
Перечисления (Enums) также могут содержать методы, что делает их мощным инструментом для инкапсуляции связанной логики. Они бесшовно работают с подсказками типов, гарантируя, что ваши функции принимают только допустимые значения — больше не нужно проверять, соответствует ли строка ожидаемым вариантам.
Задание
ЛегкоДавайте создадим систему управления заказами, которая использует перечисления (enums) для представления статусов заказов безопасным с точки зрения типов способом. Вместо того чтобы полагаться на строки, в которых можно допустить опечатку или которые могут быть недействительными, вы создадите типизированное перечисление (backed enum), которое сопоставляет каждый статус со значением, удобным для базы данных.
Вы организуете свой код в трех файлах:
OrderStatus.php— Создайте строковое перечисление (string-backed enum) с именемOrderStatusс четырьмя вариантами (cases):Pendingсо значением'pending'Processingсо значением'processing'Shippedсо значением'shipped'Deliveredсо значением'delivered'
label(), который возвращает понятное человеку описание для каждого статуса:- Pending возвращает
"Awaiting confirmation" - Processing возвращает
"Being prepared" - Shipped возвращает
"On the way" - Delivered возвращает
"Order complete"
Order.php— Создайте классOrder, который использует это перечисление. Подключите файл OrderStatus. Класс должен:- Принимать ID заказа (string) и
OrderStatusв своем конструкторе, используя продвижение свойств в конструкторе (constructor promotion) - Иметь метод
getInfo(), который возвращает"Order [id]: [status label]" - Иметь метод
getStatusValue(), который возвращает строковое значение перечисления (полезно для хранения в базе данных)
- Принимать ID заказа (string) и
main.php— Подключите файл Order. Вы получите два входных значения: ID заказа и строку статуса (например,"shipped"). ИспользуйтеtryFrom()для безопасного преобразования строкового ввода в перечислениеOrderStatus. Если статус валиден, создайте объектOrderи выведите две строки:- Результат выполнения
getInfo() - Результат выполнения
getStatusValue()
"Invalid status".- Результат выполнения
Эта задача демонстрирует, как перечисления обеспечивают безопасность типов — ваш класс Order может принимать только допустимые статусы, а метод tryFrom() позволяет безопасно обрабатывать ввод пользователя, не рискуя получить некорректные значения.
Шпаргалка
Перечисления (Enums) предоставляют типобезопасный способ определения фиксированного набора значений. Определите перечисление с помощью ключевого слова enum:
<?php
enum Status {
case Pending;
case Active;
case Completed;
}
$status = Status::Active;
echo $status->name; // Выводит: Active
Типизированные перечисления (Backed enums) связывают строковые или целочисленные значения с каждым вариантом:
<?php
enum Status: string {
case Pending = 'pending';
case Active = 'active';
case Completed = 'completed';
}
$status = Status::Active;
echo $status->value; // Выводит: active
Используйте from() для создания перечисления из его значения или tryFrom(), который возвращает null для недопустимых значений:
<?php
$status = Status::from('active'); // Возвращает Status::Active
$invalid = Status::tryFrom('unknown'); // Возвращает null
Перечисления могут содержать методы для инкапсуляции связанной логики:
<?php
enum Status: string {
case Pending = 'pending';
case Active = 'active';
public function label(): string {
return match($this) {
self::Pending => 'Awaiting',
self::Active => 'In Progress',
};
}
}
Попробуйте сами
<?php
require_once 'Order.php';
// Чтение входных данных
$orderId = trim(fgets(STDIN));
$statusString = trim(fgets(STDIN));
// TODO: Используйте OrderStatus::tryFrom() для безопасного преобразования строки статуса в перечисление (enum)
// tryFrom() возвращает null, если значение недействительно
// TODO: Если статус валиден, создайте Order и выведите:
// - Результат getInfo()
// - Результат getStatusValue()
// TODO: Если статус невалиден, выведите "Invalid status"
?>В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово $thisМетодыСвойстваКонструктор (__construct)Деструктор (__destruct)Итоги — Простой калькулятор4Наследование
Основы наследованияКлючевое слово parent::Переопределение методовКлючевое слово finalАбстрактные классыИтоги — Иерархия сотрудников7Инкапсуляция
Public, Protected, PrivateПодробный разбор модификаторов доступаГеттеры и сеттерыСокрытие данныхConstructor Promotion (8.0)Итоги — Система учета студентов10Продвинутые концепции ООП
Композиция против наследованияВнедрение зависимостейАнонимные классыПеречисления (PHP 8.1)Файберы (PHP 8.1)Глубокое погружение в клонирование объектовГенераторы и итераторы13Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн Репозиторий2Пространства имен и автозагрузка
Введение в пространства именКлючевое слово useСтандарт автозагрузки PSR-4Автозагрузчик ComposerИтоги: структурированный проект5Интерфейсы и контракты
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовИнтерфейс против абстрактного классаType Hinting с интерфейсамиИтоги — Калькулятор фигур8Магические методы
Введение в магические методы__toString и __debugInfo__get, __set, __isset, __unset__call и __callStatic__clone и клонирование объектов__serialize и __unserializeИтоги — Кастомная коллекция11Система типов и обработка ошибок
Объявление типовNullable-типыТипы объединения и пересеченияКлассы исключенийИерархия пользовательских исключенийTry, Catch, FinallyИтоги — Валидатор форм14Проект: Управление библиотекой
Обзор проектаКлассы Book и User3Свойства классов
Свойства экземпляра и статические свойстваКонстанты в классахСтатические методы и свойстваПриватные и защищенные свойстваСвойства Readonly (PHP 8.1)Итоги — Менеджер банковского счета6Полиморфизм
Снова о переопределении методовПолиморфизм через интерфейсыType Hinting и Union TypesПозднее статическое связываниеИтоги — Payment Processor9Трейты
Введение в трейтыИспользование нескольких трейтовРазрешение конфликтов трейтовАбстрактные методы в трейтахТрейты и наследование12Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн Strategy