Современный PHP 8 — enum, readonly и атрибуты
Материал дополняет ООП в PHP и ориентирован на PHP 8.1+. Устаревшие константы вместо enum и «магические» строки статусов здесь рассматриваются только как антипаттерн.
Readonly-свойства (PHP 8.1)
Модификатор readonly запрещает присвоение свойству после инициализации. Запись возможна только один раз — обычно в конструкторе.
<?php
declare(strict_types=1);
class Order
{
public function __construct(
public readonly string $id,
public readonly \DateTimeImmutable $createdAt,
private readonly float $amount,
) {}
public function total(): float
{
return $this->amount;
}
}
$order = new Order('ord-1', new \DateTimeImmutable(), 99.5);
// $order->id = 'x'; // Error: Cannot modify readonly property
Правила:
- Тип свойства обязателен (нельзя
public readonly $xбез типа). - Readonly нельзя сделать
static. - Свойство без значения по умолчанию должно быть инициализировано до конца конструктора.
Readonly-класс (PHP 8.2)
Если пометить весь класс как readonly, все его свойства становятся readonly автоматически:
readonly class Point
{
public function __construct(
public float $x,
public float $y,
) {}
}
Такой класс не может содержать обычные изменяемые свойства и не может быть унаследован не-readonly классом. Удобно для DTO и объектов-значений, которые не должны меняться после создания.
Перечисления enum (PHP 8.1)
Enum — отдельный тип для ограниченного набора вариантов. Заменяет «магические» строки и int-константы в классе.
Unit enum (без значения)
enum Status
{
case Draft;
case Published;
case Archived;
}
function canEdit(Status $status): bool
{
return match ($status) {
Status::Draft => true,
Status::Published, Status::Archived => false,
};
}
Сравнение — только через === между case одного enum. Status::Draft === 'draft' всегда ложь.
Backed enum (со значением в БД или JSON)
enum Priority: string
{
case Low = 'low';
case Normal = 'normal';
case High = 'high';
}
// Из строки (например, из БД)
$p = Priority::from('high');
// Безопасный разбор
$p = Priority::tryFrom('unknown'); // null, если нет такого значения
echo $p->value; // 'high'
echo $p->name; // 'High'
В таблице хранят колонку priority VARCHAR со значениями 'low', 'normal', 'high' и при чтении вызывают Priority::from($row['priority']).
Методы в enum
Enum может содержать методы, как класс:
enum Role: string
{
case Admin = 'admin';
case Editor = 'editor';
case Guest = 'guest';
public function label(): string
{
return match ($this) {
self::Admin => 'Администратор',
self::Editor => 'Редактор',
self::Guest => 'Гость',
};
}
public function canPublish(): bool
{
return $this === self::Admin || $this === self::Editor;
}
}
Атрибуты (PHP 8.0)
Атрибут — метаданные у класса, метода, свойства или параметра. Синтаксис: #[ИмяАтрибута(...)]. Это не комментарии: атрибуты доступны через Reflection во время выполнения.
#[\Attribute(\Attribute::TARGET_METHOD)]
class Route
{
public function __construct(
public string $path,
public array $methods = ['GET'],
) {}
}
class HomeController
{
#[Route('/')]
public function index(): string
{
return 'Главная';
}
#[Route('/about', methods: ['GET'])]
public function about(): string
{
return 'О проекте';
}
}
Чтение атрибутов (упрощённый диспетчер):
$ref = new \ReflectionMethod(HomeController::class, 'index');
$attrs = $ref->getAttributes(Route::class);
foreach ($attrs as $attr) {
$route = $attr->newInstance();
echo $route->path; // /
}
Фреймворки (Symfony, Laravel 8+) используют встроенные и пользовательские атрибуты для маршрутов, валидации, DI. В учебном коде атрибуты помогают декларативно описывать правила без дублирования в конфигурационных массивах.
Встроенный атрибут для переопределения типов
class Container
{
/** @var array<string, object> */
private array $services = [];
#[\ReturnTypeWillChange]
public function offsetGet($key): mixed
{
return $this->services[$key] ?? null;
}
}
ReturnTypeWillChange — временная метка совместимости при реализации интерфейсов, меняющих сигнатуры между версиями PHP.
Как сочетать возможности
Пример неизменяемой сущности со статусом-enum:
readonly class Article
{
public function __construct(
public string $slug,
public string $title,
public Status $status,
) {}
public function withStatus(Status $new): self
{
return new self($this->slug, $this->title, $new);
}
}
Вместо изменения полей создаётся новый объект — предсказуемое поведение без побочных эффектов.
Сравнение с прежними приёмами
| Задача | Старый подход | PHP 8+ |
|---|---|---|
| Статусы заказа | const STATUS_PAID = 2 | enum OrderStatus |
| Неизменяемый ID | private + только геттер | public readonly string $id |
| Метаданные маршрута | массив в отдельном файле | #[Route('...')] на методе |
Что изучить дальше
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). PHP как язык веб-разработки - роль серверного исполнения, базовый синтаксис и место в современном стеке. Экосистема PHP-приложений - фреймворки, инструменты, пакеты и типовые архитектурные подходы веб-разработки. PHP — это язык программирования общего назначения, который изначально создавался для динамической генерации веб-страниц. Модель исполнения PHP - жизненный цикл запроса, серверный контекст и экосистема популярных CMS. История PHP - эволюция языка от простых скриптов до зрелой платформы серверной веб-разработки. Composer в PHP - управление зависимостями, автозагрузка классов и воспроизводимая сборка проектов. Параметр opcache.fast_shutdown ускоряет завершение работы скрипта за счёт пропуска стандартной процедуры освобождения памяти. Вместо этого используется механизм сборщика мусора операционной системы. Локальная среда разработки на PHP - настройка стека, запуск приложения и отладка без продакшен-сервера. Набор советов, правил, принципов и обычаев в разработке на этом языке. Фреймворки и библиотеки PHP - организация сервисов, вспомогательные компоненты и ускорение разработки веб-приложений. Гайд по установке и настройке с написанием первой программы и её запуском. Примеры простых и полезных консольных приложений с демонстрацией концепций языка.PHP - язык веб-разработки
Экосистема PHP-приложений
Что требуется знать перед началом изучения языка программирования PHP
Модель исполнения PHP
История языка PHP
Composer - управление зависимостями в PHP
Настройка веб-сервера для работы с PHP
Локальная среда разработки на PHP
Рекомендации по разработке на PHP
Фреймворки и библиотеки PHP
Первая программа на PHP
Простые приложения на PHP