Enums в PHP: от хаоса к порядку
Вы когда-нибудь писали код, в котором статус заказа хранится как строка 'new', 'paid', 'shipped'? А потом ловили баги из-за опечатки 'shippped'? Или передавали в функцию getOrderByStatus('Active'), а там ждали 'active'? Знакомо? Тогда эта статья для вас.
Долгое время в PHP не было родных перечислений (enums). Разработчики изворачивались: использовали константы классов, массивы, даже комментарии-заглушки. Но с выходом PHP 8.1 всё изменилось. Теперь у нас есть полноценные перечисления PHP — мощный инструмент, который делает код чище, безопаснее и понятнее.
В этом руководстве мы разберём enums PHP от А до Я: от базового синтаксиса до продвинутых приёмов. Вы узнаете, как создавать перечисления, работать с ними, сравнивать и использовать в реальных проектах. Поехали!
Что такое Enum в PHP?
Enum (enumeration) — это тип данных, который ограничен набором предопределённых значений. Простыми словами: вы определяете список возможных вариантов, и переменная может принять только один из них. Никаких случайных строк, никаких непроверенных значений.
В PHP 8.1 перечисления реализованы как специальные классы. Каждое значение — это объект, а не просто константа. Это даёт массу преимуществ:
- Строгая типизация — компилятор не пропустит
'pending'вместоStatus::Pending - Безопасность — никаких случайных опечаток
- Читаемость — код говорит сам за себя
- IDE-поддержка — автодополнение работает на ура
Синтаксис Enum в PHP
Создать перечисление в PHP просто. Используйте ключевое слово enum:
<?php
enum OrderStatus
{
case New;
case Pending;
case Processing;
case Shipped;
case Delivered;
case Cancelled;
}
Теперь мы можем использовать OrderStatus как тип:
<?php
function updateOrderStatus(OrderStatus $status): void
{
// Обработка статуса
}
// Передаём значение:
updateOrderStatus(OrderStatus::Shipped);
Попробуйте передать строку 'shipped' — PHP выдаст ошибку типа. Это и есть магия enum в PHP.
Enum с бэкингом (Backed Enums)
Часто нам нужно связать каждый кейс с конкретным значением — например, числом или строкой для базы данных. В PHP это называется backed enum:
<?php
enum OrderStatus: string
{
case New = 'new';
case Pending = 'pending';
case Processing = 'processing';
case Shipped = 'shipped';
case Delivered = 'delivered';
case Cancelled = 'cancelled';
}
Теперь каждый кейс имеет строковое значение. Вы можете получить его через свойство value:
<?php
$status = OrderStatus::Shipped;
echo $status->value; // 'shipped'
А можно создать кейс из значения обратно:
<?php
$status = OrderStatus::from('shipped');
echo $status->name; // 'Shipped'
Метод from() выбросит исключение, если значение не найдено. Если хотите получить null — используйте tryFrom().
Методы в Enum: поведение внутри перечислений
Одна из крутых фич PHP enum — возможность добавлять методы прямо внутрь перечисления. Это превращает enum из простого списка констант в полноценный объект с логикой.
<?php
enum OrderStatus: string
{
case New = 'new';
case Pending = 'pending';
case Processing = 'processing';
case Shipped = 'shipped';
case Delivered = 'delivered';
case Cancelled = 'cancelled';
public function label(): string
{
return match($this) {
self::New => 'Новый заказ',
self::Pending => 'Ожидает оплаты',
self::Processing => 'В обработке',
self::Shipped => 'Отправлен',
self::Delivered => 'Доставлен',
self::Cancelled => 'Отменён',
};
}
public function isFinal(): bool
{
return in_array($this, [self::Delivered, self::Cancelled]);
}
}
Использование:
<?php
$status = OrderStatus::Shipped;
echo $status->label(); // 'Отправлен'
echo $status->isFinal(); // false
Теперь вся логика, связанная со статусами, живёт внутри самого enum. Никаких разбросанных switch-case по всему коду!
Сравнение Enum в PHP
Так как каждый кейс enum — это объект, сравнение работает через ===:
<?php
$status = OrderStatus::Shipped;
if ($status === OrderStatus::Shipped) {
echo 'Заказ отправлен';
}
// Работает и с match:
$message = match($status) {
OrderStatus::New => 'Новый заказ',
OrderStatus::Cancelled => 'Отменён',
default => 'Другой статус',
};
Важно: два разных enum-типа (например, OrderStatus и PaymentStatus) никогда не будут равны, даже если у них одинаковые имена кейсов. Это защита от случайных ошибок.
Enum и switch-case: классика
Конечно, старый добрый switch тоже работает:
<?php
function getStatusColor(OrderStatus $status): string
{
switch ($status) {
case OrderStatus::New:
return 'blue';
case OrderStatus::Pending:
return 'yellow';
case OrderStatus::Processing:
return 'orange';
case OrderStatus::Shipped:
return 'purple';
case OrderStatus::Delivered:
return 'green';
case OrderStatus::Cancelled:
return 'red';
}
}
Но я рекомендую match — он короче и безопаснее (PHP проверит, что вы обработали все кейсы, если включите строгие типы).
Перечисление всех значений Enum
Иногда нужно получить список всех возможных значений. Для этого есть статический метод cases():
<?php
$allStatuses = OrderStatus::cases();
foreach ($allStatuses as $status) {
echo $status->name . ': ' . $status->value . PHP_EOL;
}
Вывод:
New: new
Pending: pending
Processing: processing
Shipped: shipped
Delivered: delivered
Cancelled: cancelled
Это удобно для заполнения выпадающих списков, генерации документации или валидации.
Enum в реальных проектах
Давайте посмотрим, как enum php применяется в типичных задачах.
Пример 1: Статусы заказа
Блоги
Рекомендаций по книгам
Читайте также
Тестирование в C#: Unit, Integration, E2E — Полное руководство для .NET