PHP 8.5: Обзор ключевых нововведений и улучшений

PHP 8.5: Обзор ключевых нововведений и улучшений

20 ноября 2025 года состоялся релиз PHP 8.5 — значительного обновления популярного языка программирования. Этот релиз акцентирует внимание на повышении читаемости кода, упрощении отладки, усилении безопасности и удобстве работы с данными. Основные изменения направлены на то, чтобы сделать разработку более интуитивной и эффективной. Подробную информацию о релизе можно найти на официальном сайте PHP. Среди наиболее заметных новшеств:

Встроенное расширение URI для надежного парсинга URL Оператор Pipe (|>) для цепочек вызовов Улучшенная функция clone с поддержкой модификации свойств Атрибут #[\NoDiscard] для контроля возвращаемых значений Поддержка замыканий и вызовов первого класса в константных выражениях Постоянные дескрипторы cURL Share Новые функции array_first() и array_last()

Встроенное расширение URI: Надежный парсинг URL

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

$url = 'https://www.php.net/releases/8.5/ru.php';

$components = parse_url($url);
dump($components);
//array [
//  "scheme" => "https"
//  "host" => "www.php.net"
//  "path" => "/releases/8.5/ru.php"
//]

$uri = new \Uri\Rfc3986\Uri($url);
dump($uri);
//Uri\Rfc3986\Uri {
//  scheme: "https"
//  username: null
//  password: null
//  host: "www.php.net"
//  port: null
//  path: "/releases/8.5/ru.php"
//  query: null
//  fragment: null
//}

$uri = new \Uri\WhatWg\Url($url);
dump($uri);
//Uri\WhatWg\Url {
//  scheme: "https"
//  username: null
//  password: null
//  host: "www.php.net"
//  port: null
//  path: "/releases/8.5/ru.php"
//  query: null
//  fragment: null
//}

Преимущества очевидны: вместо массива с возможными отсутствующими ключами мы получаем объект с четкими геттерами, возвращающими null при отсутствии компонента. Сложный URL с аутентификацией:

$url = 'https://root:pass@www.php.net/releases/8.5/ru.php?query=params';

$uri = new \Uri\Rfc3986\Uri($url);
echo $uri->getUsername(); // root
echo $uri->getPassword(); // pass
echo $uri->getQuery();   // query=params

Особенно полезен \Uri\WhatWg\Url для международных доменов (IDN):

$url = 'https://root:pass@домер.рф/releases/8.5/ru.php?query=params';

$uri = new \Uri\WhatWg\Url($url);
echo $uri->getUnicodeHost(); // домер.рф
echo $uri->getAsciiHost();   // xn--d1acuhm.xn--p1ai

Класс WHATWG автоматически конвертирует Punycode и лучше справляется с современными требованиями браузеров.

Оператор Pipe (|>) — Читаемые цепочки обработки

Долгожданный оператор |> позволяет передавать результат одного выражения как первый аргумент в следующее, делая код линейным и легким для чтения. Пример генерации slug:

$title = ' PHP 8.5 Released ';

$slug = $title
    |> trim(...)
    |> fn($str) => str_replace(' ', '-', $str)
    |> fn($str) => str_replace('.', '', $str)
    |> strtolower(...);

echo $slug; // php-85-released

Это значительно чище вложенных вызовов и упрощает понимание последовательности операций.

Clone With: Клонирование с немедленной модификацией

Теперь функция clone принимает второй аргумент — ассоциативный массив свойств для изменения в новой копии объекта.

readonly class Color
{
    public function __construct(
        public int $red,
        public int $green,
        public int $blue,
        public int $alpha = 255,
    ) {}

    public function withAlpha(int $alpha): self
    {
        return clone($this, ['alpha' => $alpha]);
    }
}

$blue = new Color(79, 91, 147);
$transparentBlue = $blue->withAlpha(128);

Идеально для immutable-объектов и паттерна "withers".

Атрибут #[\NoDiscard]

Этот атрибут заставляет интерпретатор предупреждать, если возвращаемое значение функции игнорируется.

#[\NoDiscard]
function getPhpVersion(): string
{
    return 'PHP 8.5';
}

getPhpVersion(); // Предупреждение: возвращаемое значение не используется

Полезно для функций, где игнорирование результата может быть ошибкой (например, API-вызовы).

Замыкания в константных выражениях

Теперь статические замыкания и вызовы первого класса разрешены в контекстах, где требуются константы: атрибуты, default-значения свойств/параметров. Пример с атрибутом:

final class PostsController
{
    #[AccessControl(static fn(Request $request, Post $post): bool =>
        $request->user === $post->getAuthor()
    )]
    public function update(Request $request, Post $post): Response
    {
        // ...
    }
}

Упрощает конфигурацию без лишних классов.

Постоянные дескрипторы cURL Share

Новая функция curl_share_init_persistent() создает дескрипторы, сохраняющиеся между запросами, с автоматическим переиспользованием.

$sh = curl_share_init_persistent([CURL_LOCK_DATA_DNS, CURL_LOCK_DATA_CONNECT]);

$ch = curl_init('https://php.net/');
curl_setopt($ch, CURLOPT_SHARE, $sh);
curl_exec($ch);

Снижает overhead на инициализацию в долгоживущих приложениях (FPM, Swoole).

Функции array_first() и array_last()

Простые, но удобные помощники:

$events = [...];

$lastEvent = array_last($events); // null если массив пуст
$firstEvent = array_first($events);

Возвращают null для пустого массива — идеально сочетается с ??.

Другие заметные улучшения

  • Фатальные ошибки теперь включают полный стек вызовов (backtrace).
  • Атрибуты разрешены на константах, трейтах и свойствах.
  • #[\Override] работает со свойствами.
  • Асимметричная видимость для статических свойств.
  • Свойства в конструкторе могут быть final.
  • Новый метод Closure::getCurrent() для рекурсии в анонимных функциях.
  • Поддержка "partitioned" в cookies.
  • Новые функции: get_error_handler(), get_exception_handler(), grapheme_levenshtein().
  • Улучшения в DOM: getElementsByClassName(), insertAdjacentHTML().

Устаревшие возможности и breaking changes

  • Удалена поддержка обратных кавычек как shell_exec().
  • Неканонические типы (boolean, integer) больше не разрешены.
  • Удалена INI-настройка disable_classes.
  • Другие мелкие deprecation'ы (см. migration guide).

PHP 8.5 — это шаг вперед в удобстве и современности языка. Рекомендуется обновляться, особенно если вы цените чистый и выразительный код. Тестируйте на staging-окружении, чтобы избежать сюрпризов с deprecation'ами!