docs: English JsonRpcBundle docs, REST and MCP Bundle sections, package cards
uk/articles/from-tg/series/php-can-do/enums.md
новий файл +217
−0
Enums
Тільки цільові значення
- Додано у версії: PHP 8.1
- Що дає: нативний механізм для створення перелічуваних типів — із чіткими, типізованими значеннями замість "магічних рядків та чисел" і нескінченних const.
Трохи особистого
Це один із моїх найулюбленіших інструментів у PHP. З моменту їх появи я взагалі не уявляю розробки без enum’ів — вони зменшують кількість помилок, роблять код читабельним і гарантують типобезпеку.
Але спілкування з розробниками показує, що далеко не всі розділяють цей захват. Тому хочу поділитися своєю любов’ю до них і пояснити, чому це не просто "список значень", а справжній крок вперед для PHP.
Типи enum’ів
PHP має два різновиди enum’ів.
1. Backed Enum — із базовим значенням (string або int)
Кожен case має прив’язане значення, це дозволяє порівнювати його з іншими значеннями, серіалізувати, зберігати його в БД, та при цьому бути впевненим, що значення завжди буде одним з дозволених в переліченні.
enum Status: string
{
case DRAFT = 'draft';
case ACTIVE = 'active';
case ARCHIVED = 'archived';
}
Для чого:
- зручно в статусах замовлень, документів, платежів, типів повідомлень, типів працівників, тощо;
- легко зберігати в базі як звичайний рядок;
- можна отримати enum через
Status::from('draft')або безпечно —tryFrom('draft').
2. Pure Enum — без бекінгу
Просто набір унікальних case без значень. Використовується тоді, коли значення не потрібне — важливий сам факт "стану" або "режиму".
enum Direction
{
case NORTH;
case SOUTH;
case EAST;
case WEST;
}
Для чого:
- для внутрішніх логічних станів або режимів роботи;
- коли не треба нічого зберігати у БД;
- коли досить просто перевірити
if ($direction === Direction::NORTH).
Більше, ніж просто перелік
Більшість вважає, що enum — це просто заміна const. Насправді це класоподібна конструкція, у якій можна (і треба!) додавати методи, поведінку, статичні методи та перетворення значень.
Приклад enum із методами
enum Status: string
{
case DRAFT = 'draft';
case ACTIVE = 'active';
case ARCHIVED = 'archived';
// 🔹 Нестатичний метод — для конкретного значення
public function label(): string
{
return match($this) {
self::DRAFT => 'Чернетка',
self::ACTIVE => 'Активна',
self::ARCHIVED => 'Архівована',
};
}
// 🔹 Статичний метод — спільний для всіх
public static function visible(): array
{
return [self::DRAFT, self::ACTIVE];
}
}
echo Status::ACTIVE->label(); // Активна
print_r(Status::visible()); // [Status::DRAFT, Status::ACTIVE]
Інший приклад
Статуси документів, каналів, ролей:
enum Channel: string
{
case EMAIL = 'email';
case SMS = 'sms';
case TELEGRAM = 'telegram';
public function icon(): string
{
return match($this) {
self::EMAIL => '✉️',
self::SMS => '📱',
self::TELEGRAM => '💬',
};
}
public function getSenderFQCN(): string
{
return match($this) {
self::EMAIL => EmailSender::class,
self::SMS => SMSSender::class,
self::TELEGRAM => TelegramSender::class,
};
}
public static function fromString(string $value): ?self
{
return self::tryFrom($value);
}
}
Висновок
Enum’и — це одне із найвдаліших оновлень в PHP за останні роки. Вони дисциплінують код, роблять модель даних передбачуваною й забезпечують реальну типобезпеку.
Я вже не уявляю розробки без enum’ів. І якщо ти досі не використовуєш їх у своїх проєктах — просто спробуй, через тиждень без них ти вже не зможеш писати старим способом.
Doctrine + Enum
Я так люблю enum’и, що зробив навіть власний пакет — ufo-tech/doctrine-helper, який навчає Doctrine розуміти enum у типізованих полях сутності і створювати під них ENUM() тип поля в MySQL.
1. Створи свій PHP Enum для поля сутності
<?php
namespace App;
enum MyEnum: string
{
case CASE_1 = 'Мій варіант 1';
case CASE_2 = 'Мій варіант 2';
}
2. Створи власний DBAL-тип і наслідуй Ufo\DoctrineHelper\DBAL\AbstractEnumType
<?php
namespace App\DBAL;
use BackedEnum;
use App\MyEnum;
class MyEnumType extends AbstractEnumType
{
protected string|BackedEnum $enum = MyEnum::class;
}
3. Зареєструй новий тип у Doctrine
doctrine:
dbal:
types:
App\MyEnum: 'App\DBAL\MyEnumType'
mapping_types:
enum: string
4. Використовуй PHP Enum для зберігання й зміни значення
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use App\MyEnum;
#[ORM\Entity]
#[ORM\Table(name: 'demo')]
class Demo
{
#[ORM\Column(type: MyEnum::class, nullable: false)]
protected string $case;
public function __construct(MyEnum $case)
{
$this->case = $case->value;
}
public function changeCase(MyEnum $case): void
{
$this->case = $case->value;
}
public function getCase(): string
{
return $this->case;
}
}
Таким чином MySQL ENUM поводиться як повноцінний PHP Enum — із типобезпекою, автопідказками IDE та без ручного кастингу.
Вперше опубліковано в Telegram-каналі «Створений щоб помирати» 24.10.2025; розділ «Doctrine + Enum» — окремим постом того ж дня.