Что нового в PHP 8.0-8.4: Property Hooks, Enums, Readonly | IT-tower

📑 Содержание

Введение

Между релизами PHP 8.0 (ноябрь 2020) и PHP 8.4 (ноябрь 2024) прошло ровно четыре года. За это время язык прошел путь от «современного PHP с улучшениями» до «строго типизированного языка с продвинутой мета-системой». Если 8.0 был про синтаксический сахар, то версии 8.1–8.4 сосредоточились на архитектуре, безопасности типов и производительности.

В этой статье разберем ключевые улучшения, которые появились в PHP между версиями 8.0 и 8.4, и покажем, как изменился подход к написанию кода.

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

Одно из самых долгожданных изменений. До 8.1 для работы с фиксированным набором значений использовали константы классов или просто строки, что приводило к ошибкам и отсутствию автодополнения в IDE.

Как было в 8.0

PHP 8.0
class OrderStatus {
    const PENDING = 'pending';
    const PAID = 'paid';
    const SHIPPED = 'shipped';
}

$status = OrderStatus::PENDING;
// Нет защиты от опечаток: $status = 'panding'; — пройдет без ошибок

Как стало в 8.1

PHP 8.1
enum OrderStatus: string {
    case PENDING = 'pending';
    case PAID = 'paid';
    case SHIPPED = 'shipped';
}

$status = OrderStatus::PENDING;
// Строгая типизация: $status = 'panding'; — ошибка компиляции

Enums поддерживают методы, интерфейсы и backed-значения (string/int). Это кардинально изменило работу с состояниями в Laravel, Symfony и Битрикс-разработке.

Неизменяемость: от свойств к классам — PHP 8.1 и 8.2

Readonly properties (8.1)

Появилась возможность объявлять свойства как readonly — их можно установить только один раз (в конструкторе или при инициализации), после чего они становятся неизменяемыми.

Readonly properties
class User {
    public function __construct(
        public readonly string $name,
        public readonly int $age
    ) {}
}

$user = new User('John', 30);
// $user->name = 'Jane'; — Fatal error: Cannot modify readonly property

Это идеально для DTO и Value Objects — объектов, которые не должны меняться после создания.

Readonly classes (8.2)

Логичное продолжение: теперь можно объявить весь класс как readonly, и все его свойства автоматически станут неизменяемыми.

Readonly class
readonly class Point {
    public function __construct(
        public float $x,
        public float $y
    ) {}
}

Меньше бойлерплейта, больше семантики.

Property Hooks и асимметричная видимость — PHP 8.4

Это революционное изменение, которое убивает необходимость в геттерах и сеттерах для многих сценариев.

Property Hooks

Теперь логика чтения и записи свойства встраивается прямо в его объявление:

Property Hooks
class User {
    public string $fullName {
        get => $this->firstName . ' ' . $this->lastName;
        set => [$this->firstName, $this->lastName] = explode(' ', $value, 2);
    }
    
    public function __construct(
        private string $firstName,
        private string $lastName
    ) {}
}

$user = new User('John', 'Doe');
echo $user->fullName; // "John Doe"
$user->fullName = 'Jane Smith'; // автоматически обновит firstName и lastName

Асимметричная видимость (Asymmetric Visibility)

Можно сделать свойство публичным для чтения, но приватным для записи прямо в сигнатуре:

Asymmetric Visibility
class User {
    public function __construct(
        public private(set) string $status = 'active'
    ) {}
    
    public function deactivate(): void {
        $this->status = 'inactive'; // OK, пишем изнутри класса
    }
}

$user = new User();
echo $user->status; // OK, читаем снаружи
// $user->status = 'deleted'; — Fatal error: Cannot modify private(set) property

Это решает проблему «публичных свойств, которые нельзя менять извне» без написания лишних методов.

Эволюция системы типов — PHP 8.1, 8.2, 8.3

Intersection Types (8.1)

Можно требовать, чтобы объект реализовывал несколько интерфейсов одновременно:

Intersection Types
function process(Countable&Iterator $collection): void {
    // $collection гарантированно поддерживает и count(), и итерацию
}

Standalone types: true, false, null (8.2)

Эти типы стали самостоятельными. Раньше их можно было использовать только в union (int|null), теперь — отдельно:

Standalone types
function getStatus(): false { return false; }
function findUser(): null { return null; }

DNF Types — Disjunctive Normal Form (8.2)

Комбинация union и intersection типов в одном объявлении:

DNF Types
function process((A&B)|C $param): void {
    // $param может быть либо (объектом, реализующим A И B), либо C
}

Типизация стала математически строгой и позволяет описывать очень сложные контракты.

Typed class constants (8.3)

Теперь константы класса можно типизировать:

Typed constants
class Config {
    const string APP_NAME = 'MyApp';
    const int MAX_RETRIES = 3;
    const array ALLOWED_ROLES = ['admin', 'user'];
}

Защита от случайного изменения типа константы при рефакторинге.

Fibers — асинхронность без ада колбэков (PHP 8.1)

Fibers (волокна) — это низкоуровневый механизм для создания прерываемых функций. Сам по себе PHP не стал асинхронным «из коробки» для веба, но Fibers стали фундаментом для библиотек вроде ReactPHP, Amp и Laravel Octane (Swoole/RoadRunner).

Fibers
$fiber = new Fiber(function (): void {
    $value = Fiber::suspend('fiber suspended');
    echo 'Fiber resumed with: ' . $value . PHP_EOL;
});

$fiber->start();
$fiber->resume('hello');

Это позволяет писать асинхронный код в синхронном стиле, без callback-hell и Promise-цепочек.

Улучшения для работы со строками и массивами

First-class callable syntax (8.1)

Более элегантный способ передачи функций как callable:

First-class callable
// PHP 8.0
$fn = 'strlen';
$result = array_map($fn, $array);

// PHP 8.1
$fn = strlen(...);
$result = array_map($fn, $array);

array_is_list() (8.1)

Проверяет, является ли массив списком (ключи — последовательные целые числа от 0):

array_is_list
array_is_list([1, 2, 3]); // true
array_is_list(['a' => 1, 'b' => 2]); // false

json_validate() (8.3)

Быстрая проверка валидности JSON без его парсинга и потребления памяти:

json_validate
if (json_validate($jsonString)) {
    $data = json_decode($jsonString, true);
}

Отказ от динамических свойств — PHP 8.2 (и боль для легаси)

В PHP 8.0 и раньше можно было динамически добавлять свойства к объектам:

Динамические свойства
class User {
    public string $name;
}

$user = new User();
$user->email = 'test@example.com'; // Работало в 8.0

В PHP 8.2 это вызывает Deprecated, а в PHP 9.0 станет фатальной ошибкой. Это заставляет разработчиков явно объявлять все свойства в классах, что улучшает читаемость и безопасность кода.

Синтаксические улучшения PHP 8.3 и 8.4

Dynamic class constant fetch (8.3)

Теперь можно получать константы класса по динамическому имени:

Dynamic constant fetch
class Config {
    const API_KEY = 'secret';
}

$keyName = 'API_KEY';
$value = Config::{$keyName}; // Раньше так нельзя было

Вызов new без скобок (8.4)

Упрощение синтаксиса для цепочек вызовов:

new без скобок
// PHP 8.3 и раньше
(new User())->getName();

// PHP 8.4
new User()->getName();

Атрибут #[\Deprecated] (8.4)

Теперь можно помечать собственные функции, методы и классы как устаревшие:

Атрибут Deprecated
#[\Deprecated(
    message: "Используй newMethod() вместо oldMethod()",
    since: "2.0"
)]
public function oldMethod(): void {
    // ...
}

При вызове такого метода PHP выдаст предупреждение с вашим сообщением.

Производительность и оптимизации

Между 8.0 и 8.4 произошли значительные улучшения в производительности:

  • JIT-компилятор стал стабильнее и начал давать реальный прирост в CPU-интенсивных задачах
  • Оптимизация работы с массивами снизила потребление памяти на 10-15%
  • Улучшения в Zend Engine ускорили выполнение типичных веб-запросов на 5-8%
  • Fibers открыли путь к асинхронным фреймворкам без overhead на контекстные переключения

Заключение: Какой PHP выбрать в 2026 году?

Для новых проектов на Laravel: Целиться в PHP 8.3 или 8.4. Современные версии Laravel (11, 12) активно используют Enums, Readonly classes и Property Hooks.

Для Битрикс-разработки: PHP 8.1 или 8.2 — текущий «золотой стандарт». PHP 8.3/8.4 пока вызывают проблемы с ядром из-за устаревших паттернов.

Для легаси-проектов: Миграция с 8.0 на 8.2+ требует тщательного тестирования из-за breaking changes (особенно отказ от динамических свойств).

За четыре года PHP превратился из «языка для быстрого прототипирования» в «зрелый язык с продвинутой системой типов». Если вы пишете код в стиле PHP 8.0 на версии 8.4, вы упускаете 80% современных возможностей языка.

✅ Итог: PHP 8.4 — это не просто новая версия, а кульминация четырёх лет эволюции. Хуки свойств, асимметричная видимость и типизированные константы делают код более выразительным и безопасным, а отказ от динамических свойств заставляет писать более предсказуемый код.

Готовы обсудить ваш проект?

Оставьте заявку, и я свяжусь с вами в течение 2 часов в рабочее время (Пн-Пт 9:00-18:00).