🐘
Хостинг

Что нового в PHP 8.4: property hooks, асимметричная видимость и другое

06.11.2026
← Все статьи

PHP 8.4 вышел в ноябре 2024 года и стал одним из самых заметных обновлений последних лет. В нём появились property hooks, которые меняют работу со свойствами классов, раздельные права на чтение и запись свойства, новые функции для массивов и DOM API, корректно понимающий HTML5. Разберём эти нововведения на простых примерах и обсудим, на что обратить внимание перед переводом сайта на хостинге на 8.4.

Property hooks: проверки без геттеров и сеттеров

Раньше, чтобы проверять значение при записи в свойство, его делали закрытым и писали отдельные методы getName() и setName(). Это порождало много однотипного кода. В PHP 8.4 логику проверки и преобразования можно привязать прямо к свойству. Внешний код работает с обычным свойством, но при каждом чтении или записи выполняется ваш код.

Возьмём класс товара для небольшого интернет-магазина в Ташкенте. Лишние пробелы в названии должны удаляться автоматически, цена не может быть отрицательной, а полное название собирается из имени и цены:

class Product
{
    public string $name {
        set(string $value) {
            $this->name = trim($value);
        }
    }

    public int $price {
        set(int $value) {
            if ($value < 0) {
                throw new InvalidArgumentException('Цена не может быть отрицательной');
            }
            $this->price = $value;
        }
    }

    // Виртуальное свойство: только чтение, в памяти не хранится
    public string $fullName {
        get => $this->name . ' - ' . number_format($this->price, 0, '.', ' ') . ' сум';
    }
}

$p = new Product();
$p->name = '  Чайник  ';
$p->price = 85000;
echo $p->fullName; // Чайник - 85 000 сум

Свойство $fullName виртуальное: в него ничего не записывается, значение вычисляется при каждом чтении. Хуки можно объявлять и в интерфейсах, то есть интерфейс теперь может требовать не только методы, но и свойства. В больших проектах это заметно очищает код.

Асимметричная видимость: читать снаружи, писать изнутри

Часто свойство должно быть доступно для чтения всем, а изменять его может только сам класс. Например, статус заказа виден внешнему коду, но меняется лишь через специальный метод. В PHP 8.4 право записи указывается отдельно:

class Order
{
    public private(set) string $status = 'new';

    public function pay(): void
    {
        $this->status = 'paid';
    }
}

$o = new Order();
echo $o->status;          // new
$o->pay();
echo $o->status;          // paid
$o->status = 'cancelled'; // Error: запись снаружи запрещена

Раньше для этого требовались закрытое свойство и отдельный геттер, теперь хватает одной строки. Вариант protected(set) разрешает запись ещё и наследникам.

Новые функции для массивов

Добавлены четыре функции для поиска по условию: array_find(), array_find_key(), array_any() и array_all(). Они заметно сокращают код, который раньше писали через foreach или array_filter(). Пример из системы записи на приём в клинике в Самарканде:

$appointments = [
    ['id' => 1, 'doctor' => 'Karimov', 'confirmed' => true],
    ['id' => 2, 'doctor' => 'Aliyeva', 'confirmed' => false],
    ['id' => 3, 'doctor' => 'Karimov', 'confirmed' => true],
];

// Первая неподтверждённая запись
$pending = array_find($appointments, fn($a) => !$a['confirmed']);

// Есть ли хотя бы одна неподтверждённая?
$hasPending = array_any($appointments, fn($a) => !$a['confirmed']);

// Все ли подтверждены?
$allConfirmed = array_all($appointments, fn($a) => $a['confirmed']);

Небольшие, но полезные изменения

Чтобы создать объект и сразу вызвать его метод, больше не нужны скобки вокруг new. Вместо (new DateTimeImmutable())->format('Y-m-d') теперь достаточно new DateTimeImmutable()->format('Y-m-d'). Мелочь, но код читается легче.

Для многоязычных сайтов появились mb_trim(), mb_ltrim(), mb_rtrim(), mb_ucfirst() и mb_lcfirst(). Они правильно работают с кириллицей и другими многобайтовыми символами, что удобно при обработке текстов на русском и узбекском. Ещё одно новшество — атрибут #[\Deprecated], которым можно помечать устаревшие функции в собственном коде, чтобы при их вызове выводилось предупреждение.

В расширении DOM появился класс Dom\HTMLDocument, который разбирает HTML5 так же, как браузеры, и поддерживает поиск элементов по CSS-селекторам. Также добавлены ленивые объекты (lazy objects): объект создаётся только тогда, когда он действительно нужен. Этот механизм в первую очередь рассчитан на фреймворки и библиотеки.

Устаревшие возможности и удалённые расширения

Перед переходом важно знать, что объявлено устаревшим, потому что это обычно приводит к росту предупреждений в журнале. Чаще всего встречается неявный nullable-тип: запись function save(Product $p = null) теперь считается устаревшей, правильно писать ?Product $p = null. В старых плагинах таких мест много, поэтому после перехода на 8.4 в журнале может появиться много сообщений Deprecated.

Как перевести сайт на хостинге на 8.4

Новые возможности приносят пользу при написании нового кода, а для существующего сайта главная цель перехода — скорость и более долгая поддержка безопасности. Сначала проверьте, поддерживают ли 8.4 ваша CMS, тема и плагины. Затем сделайте резервную копию файлов и базы данных и по возможности протестируйте сайт на копии.

На хостинге sayt.uz версия PHP выбирается для каждого сайта отдельно в панели ISPmanager, поэтому перевод одного сайта на 8.4 не затрагивает остальные. После перехода следите за журналом ошибок пару дней. Если появится Fatal error, верните прежнюю версию и спокойно исправьте проблему. Если есть только предупреждения Deprecated, сайт продолжит работать, но помните, что в следующих версиях они могут превратиться в ошибки.

Похожие статьи

🟢 Деплой Nuxt на сервер: SSR, статическая генерация, PM2 и Nginx 🔀 nvm: управление версиями Node.js, переключение и .nvmrc 📧 Как создать почтовый ящик в ISPmanager и настроить его 🚀 Деплой без простоя: папки релизов и переключение через symlink
🌐 Язык
🇺🇿 O'zbek 🇺🇿 Ўзбек 🇷🇺 Русский ✓ 🇬🇧 English