📑 Содержание
Введение
Между релизами 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
class OrderStatus {
const PENDING = 'pending';
const PAID = 'paid';
const SHIPPED = 'shipped';
}
$status = OrderStatus::PENDING;
// Нет защиты от опечаток: $status = 'panding'; — пройдет без ошибок
Как стало в 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 — их можно установить только один раз (в конструкторе или при инициализации), после чего они становятся неизменяемыми.
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 Point {
public function __construct(
public float $x,
public float $y
) {}
}
Меньше бойлерплейта, больше семантики.
Property Hooks и асимметричная видимость — PHP 8.4
Это революционное изменение, которое убивает необходимость в геттерах и сеттерах для многих сценариев.
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)
Можно сделать свойство публичным для чтения, но приватным для записи прямо в сигнатуре:
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)
Можно требовать, чтобы объект реализовывал несколько интерфейсов одновременно:
function process(Countable&Iterator $collection): void {
// $collection гарантированно поддерживает и count(), и итерацию
}
Standalone types: true, false, null (8.2)
Эти типы стали самостоятельными. Раньше их можно было использовать только в union (int|null), теперь — отдельно:
function getStatus(): false { return false; }
function findUser(): null { return null; }
DNF Types — Disjunctive Normal Form (8.2)
Комбинация union и intersection типов в одном объявлении:
function process((A&B)|C $param): void {
// $param может быть либо (объектом, реализующим A И B), либо C
}
Типизация стала математически строгой и позволяет описывать очень сложные контракты.
Typed class constants (8.3)
Теперь константы класса можно типизировать:
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).
$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:
// 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([1, 2, 3]); // true
array_is_list(['a' => 1, 'b' => 2]); // false
json_validate() (8.3)
Быстрая проверка валидности JSON без его парсинга и потребления памяти:
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)
Теперь можно получать константы класса по динамическому имени:
class Config {
const API_KEY = 'secret';
}
$keyName = 'API_KEY';
$value = Config::{$keyName}; // Раньше так нельзя было
Вызов new без скобок (8.4)
Упрощение синтаксиса для цепочек вызовов:
// PHP 8.3 и раньше
(new User())->getName();
// PHP 8.4
new User()->getName();
Атрибут #[\Deprecated] (8.4)
Теперь можно помечать собственные функции, методы и классы как устаревшие:
#[\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% современных возможностей языка.