MidТеория2 min

Перечисления Enums

Backed enums, methods, implements, cases

Перечисления (Enums) — PHP 8.1+

Pure Enums

<?php
declare(strict_types=1);

enum Suit
{
    case Hearts;
    case Diamonds;
    case Clubs;
    case Spades;
}

$suit = Suit::Hearts;
echo $suit->name;  // 'Hearts'

// Type hint
function playCard(Suit $suit): void
{
    echo "Playing {$suit->name}";
}
playCard(Suit::Spades);  // Playing Spades

// Comparison
var_dump(Suit::Hearts === Suit::Hearts);    // true
var_dump(Suit::Hearts === Suit::Diamonds);  // false

// List all cases
$allSuits = Suit::cases();
// [Suit::Hearts, Suit::Diamonds, Suit::Clubs, Suit::Spades]

Backed Enums

<?php
declare(strict_types=1);

// String-backed enum
enum Status: string
{
    case Active = 'active';
    case Inactive = 'inactive';
    case Pending = 'pending';
    case Banned = 'banned';
}

$status = Status::Active;
echo $status->value;  // 'active'
echo $status->name;   // 'Active'

// Create from value
$status = Status::from('active');      // Status::Active
$status = Status::tryFrom('unknown');  // null (no exception)
// $status = Status::from('unknown');  // ValueError!

// Int-backed enum
enum Priority: int
{
    case Low = 1;
    case Medium = 2;
    case High = 3;
    case Critical = 4;
}

echo Priority::High->value;  // 3

// Useful for database storage
$priority = Priority::from($row['priority']);  // From DB value
$dbValue = $priority->value;                    // To DB value

Запомни: from() выбрасывает ValueError если значение не найдено. tryFrom() возвращает null. Pure enums не имеют ->value, только ->name. Backed enums могут быть string или int (не float, не bool).

Методы и интерфейсы в Enums

<?php
declare(strict_types=1);

interface HasLabel
{
    public function label(): string;
}

enum Color: string implements HasLabel
{
    case Red = '#FF0000';
    case Green = '#00FF00';
    case Blue = '#0000FF';

    // Instance methods
    public function label(): string
    {
        return match($this) {
            self::Red => 'Красный',
            self::Green => 'Зелёный',
            self::Blue => 'Синий',
        };
    }

    // Static methods
    public static function primary(): array
    {
        return [self::Red, self::Green, self::Blue];
    }

    // Constants (allowed)
    public const DEFAULT = self::Red;
}

echo Color::Red->label();       // Красный
echo Color::Red->value;         // #FF0000
echo Color::DEFAULT->label();   // Красный

// Use in match/switch
$color = Color::from('#00FF00');
echo $color->label();  // Зелёный

Ограничения Enums

<?php
declare(strict_types=1);

enum Status: string
{
    case Active = 'active';
    case Inactive = 'inactive';

    // Enums CANNOT have:
    // - Properties (no $this->prop)
    // - Constructor (__construct is forbidden)
    // - Dynamic state

    // Enums CAN have:
    // - Methods (instance and static)
    // - Constants
    // - Implement interfaces
    // - Use traits (without properties!)
}

// Enums cannot be instantiated
// $s = new Status();  // Error!

// Enums cannot be extended
// enum AdvancedStatus extends Status {}  // Error!

// Traits in enums (without properties)
trait Describable
{
    public function describe(): string
    {
        return "Enum case: {$this->name}";
    }
}

enum Role: string
{
    use Describable;

    case Admin = 'admin';
    case User = 'user';
}
echo Role::Admin->describe();  // Enum case: Admin

Ловушка экзамена: Enums НЕ могут иметь свойства, конструктор, быть унаследованы или инстанцированы через new. Они МОГУТ иметь методы, константы, реализовать интерфейсы и использовать трейты (без свойств). Enum case — это объект типа самого enum.


Проверь себя

Свойство `->value` доступно у...

Могут ли enums иметь свойства?

Можно ли наследовать enum?

Какие типы допустимы для backed enums?

Что вернёт `Status::tryFrom('unknown')`?