🚀
Хостинг

PHP 8.5: pipe-оператор, расширение URI и другие новые функции

12.11.2026
← Все статьи

PHP 8.5 вышел в ноябре 2025 года. Он не принёс таких глубоких изменений, как 8.4, но добавил несколько вещей, которые заметно упрощают повседневную работу. Больше всего обсуждали pipe-оператор, позволяющий выстраивать вызовы функций в цепочку. Кроме того, появились стандартное расширение для работы с URL, функции для получения первого и последнего элемента массива и атрибут, предупреждающий о проигнорированном результате. Разберём каждое нововведение на практических примерах.

Pipe-оператор: цепочка вместо вложенных вызовов

Когда значение нужно пропустить через несколько функций подряд, код в PHP обычно получается вложенным. Например, чтобы сделать из заголовка короткий адрес страницы, нужно убрать пробелы по краям, перевести в нижний регистр и заменить пробелы дефисами. Вложенный код читается справа налево, а скобок становится всё больше. Новый оператор |> передаёт значение слева направо — в том же порядке, в каком выполняются действия.

Сравним код, который строит адреса страниц номеров для сайта гостиницы в Бухаре:

$title = '  Lyuks Xona Bog Tomonda  ';

// Раньше: вложенные вызовы
$slug = str_replace(' ', '-', strtolower(trim($title)));

// PHP 8.5: pipe-оператор
$slug = $title
    |> trim(...)
    |> strtolower(...)
    |> (fn($s) => str_replace(' ', '-', $s));

echo $slug; // lyuks-xona-bog-tomonda

Здесь важны два правила. Во-первых, справа от оператора должно стоять вызываемое выражение, принимающее один параметр, поэтому используется синтаксис first-class callable вроде trim(...). Во-вторых, стрелочную функцию (fn) обязательно нужно заключать в скобки, иначе будет синтаксическая ошибка. Функции с несколькими параметрами, такие как str_replace(), оборачиваются именно в такую стрелочную функцию.

Изменение свойств при клонировании

Readonly-свойства есть в PHP с версии 8.1, но создавать копию объекта с одним изменённым значением было неудобно: в клоне readonly-свойство перезаписать нельзя. В PHP 8.5 функция clone() принимает вторым аргументом массив новых значений. Это сильно упрощает работу с неизменяемыми объектами.

final class Price
{
    public function __construct(
        public readonly int $amount,
        public readonly string $currency = 'UZS',
    ) {}

    public function discount(int $percent): static
    {
        return clone($this, ['amount' => intdiv($this->amount * (100 - $percent), 100)]);
    }
}

$price = new Price(400000);
echo $price->discount(10)->amount; // 360000

Расширение URI: корректный разбор адресов

Много лет для разбора URL в PHP использовалась функция parse_url(). Однако она не полностью соответствует ни одному стандарту и некоторые необычные адреса понимает иначе, чем браузер, что может приводить к уязвимостям. В PHP 8.5 добавлено встроенное расширение URI с двумя классами: Uri\Rfc3986\Uri по стандарту RFC 3986 и Uri\WhatWg\Url по стандарту WHATWG, которым следуют браузеры.

$uri = new Uri\Rfc3986\Uri('https://example.uz/katalog?page=2');

echo $uri->getHost();  // example.uz
echo $uri->getPath();  // /katalog
echo $uri->getQuery(); // page=2

Расширение особенно полезно сайтам, которые проверяют ссылки от пользователей. Если, например, перенаправление разрешено только на собственный домен, разбор адреса так же, как это делает браузер, помогает защититься от уязвимости открытого редиректа.

array_first(), array_last() и атрибут NoDiscard

Чтобы получить первый или последний элемент массива, раньше приходилось использовать reset(), end() или array_key_first(). Теперь функции array_first() и array_last() сразу возвращают значение, а для пустого массива — null. Это сокращает код, например, при получении последнего заказа или первого комментария.

Если результат функции, помеченной атрибутом #[\NoDiscard], не используется, PHP выдаёт предупреждение. Атрибут предназначен для функций, чей результат важен, например для функции сохранения, возвращающей признак ошибки. Если результат нужно намеренно проигнорировать, перед вызовом пишут (void).

#[\NoDiscard("проверьте результат сохранения")]
function save(array $data): bool
{
    // ... запись в базу
    return true;
}

save($form);          // Warning: результат не использован
$ok = save($form);    // правильно
(void) save($form);   // намеренно игнорируем

Изменения, упрощающие отладку

Раньше при фатальной ошибке, например при нехватке памяти или превышении времени выполнения, в журнал попадала только строка с ошибкой. В PHP 8.5 для таких ошибок тоже выводится стек вызовов (backtrace), поэтому проще понять, каким путём код пришёл к проблеме. Также добавлены функции get_error_handler() и get_exception_handler(), возвращающие текущий установленный обработчик.

Кроме того, в константных выражениях, например в параметрах атрибутов, теперь можно использовать статические замыкания. Это удобно для фреймворков, которые описывают правила валидации через атрибуты. Для повторных запросов появились постоянные разделяемые дескрипторы cURL, позволяющие переиспользовать DNS-кеш и данные соединения.

Что устарело и что проверить перед переходом

В PHP 8.5 несколько старых конструкций объявлены устаревшими. Чаще всего встречаются:

Эти изменения не останавливают сайт, но увеличивают количество предупреждений Deprecated в журнале. Перед переходом на 8.5 проверьте, что ваша CMS и плагины официально поддерживают эту версию: после выхода новой версии плагинам нужно время на адаптацию. Для работающего сайта безопаснее всего сначала проверить всё на тестовой копии и только потом переключать основной сайт.

На хостинге sayt.uz версия PHP выбирается для каждого сайта отдельно в панели ISPmanager, поэтому 8.5 можно сначала опробовать на тестовом поддомене, например test.example.uz. Если нужной версии в панели нет, уточните её наличие через техподдержку в кабинете.

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

📦 Переезд с Plesk на другую панель: что забрать и о чём не забыть ⏱️ Как ежеминутный cron нагружает сервер и как его облегчить 🧪 Как разместить Flask-приложение на хостинге: wsgi, Passenger, Gunicorn 🧰 Как включить расширения PHP: intl, gd, imagick, zip
🌐 Язык
🇺🇿 O'zbek 🇺🇿 Ўзбек 🇷🇺 Русский ✓ 🇬🇧 English