PHP 8.2: Головні нововведення

Огляд для оновлення з PHP 8.1.x до 8.2.x: нові можливості мови, захист чутливих параметрів у трасуванні, суворіші правила для рядків і каталогів, плюс deprecations, які краще закрити до наступного релізу.

Зміст (Оглавлення)


PHP 8.2 посилює вимогу до явності: readonly-класи, виразніші типи (зокрема DNF), атрибут #[SensitiveParameter] проти витоку секретів у backtrace. Також змінюється поведінка низки функцій (ASCII-регістр без locale, str_split(''), glob() за open_basedir) і оголошуються застарілими динамічні властивості без явного дозволу.

#[SensitiveParameter] і трасування

#[\SensitiveParameter] приховує значення параметра у stack traces — менше випадкових паролів у логах.

function connect(#[\SensitiveParameter] string $password): void
{
    throw new RuntimeException('fail');
}

Не покладайтеся лише на атрибут: у проді не виводьте сирі винятки клієнту, а логи будуйте з дисципліною щодо секретів.

Практичний рецепт: позначайте секрети на межі

Ставте #[\SensitiveParameter] на параметри, які можуть потрапити в exceptions (обгортки клієнтів, auth helper’и). Stack trace лишається корисним, але секрети не «витікають» у логи.

final class ApiClient
{
    public function __construct(
        private readonly string $baseUrl,
        #[\SensitiveParameter] private readonly string $token,
    ) {}
}

Readonly-класи

readonly class робить усі властивості екземпляра readonly і ініціалізує їх у конструкторі.

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

Зручно для immutable value object і DTO: після конструктора граф об’єкта не змінюється «ззовні» без явних копій.

Окремі типи (null, false, true) та DNF

null, false, true можна використовувати як окремі типи в оголошеннях (не лише як частина union у старих формах).

DNF (диюнктивна нормальна форма) поєднує union і intersection у нормалізованому вигляді — наприклад (A&B)|null, щоб описати API без втрати nullability.

function accepts((Countable&Traversable)|null $c): void {}

Константи в трейтах і enum у константних виразах

  • Константи в трейтах.
  • Звернення до enum у дозволених константних контекстах.

INI: error_log_mode

error_log_mode задає права файлу error log під час створення PHP.

Розширення Random

Розширення Random зводить до ладу API генерації випадкових чисел: зрозуміліші рушії, менше випадкового змішування старих функцій. Для нового коду з відтворюваними seed або криптостійкими токенами орієнтуйтеся на класи Random\Engine і Random\Randomizer з мануала.

Практичний рецепт: Randomizer для токенів і вибірки

$engine = new Random\Engine\Mt19937(random_int());
$randomizer = new Random\Randomizer($engine);
$token = $randomizer->getBytesFromString('0123456789abcdef', 32);

У тестах використовуйте seeded engine для відтворюваності; для секретів оберіть криптографічно доречний Random\Engine за документацією.

Розширення: cURL, PCRE

  • cURL: CURLINFO_EFFECTIVE_METHOD, curl_upkeep(), нові константи залежно від libcurl.
  • PCRE: модифікатор n — звичайні групи не захоплюють, лише іменовані.

Зворотно несумісні зміни (міграція)

Дата й час

  • Tentative static у factory-методів DateTime / DateTimeImmutable.
  • Суворіші відносні формати для number.

Стандартна бібліотека

  • Базові функції регістру — лише ASCII, не locale; локалізований регістр — mbstring.
  • str_split('') повертає порожній масив.
  • glob / GlobIterator і open_basedir — зміни []/false і попереджень.
  • FilesystemIterator: SKIP_DOTS більше не «вшитий» у стару поведінку за замовчуванням — задайте прапорці явно.
  • ksort / krsort: при SORT_REGULAR застосовуються правила PHP 8 для числових рядків послідовно з іншими порівняннями.
  • var_export експортує повністю кваліфіковані імена класів (початковий зворотний слеш не опускається).

ODBC / PDO_ODBC

Екранування імені користувача та пароля при дописуванні до рядка підключення.

Примітка: date_default_timezone_get() у деяких випадках може повертати UTC, якщо зону не задано явно — перевірте припущення про часовий пояс після оновлення.

SPL

Деякі методи SplFileObject суворіше дотримуються сигнатур; для частини методів звузили типи повернення (hasChildren, getChildren тощо) — перегляньте власні нащадки.

Deprecations

Динамічні властивості

Створення динамічних властивостей на довільних класах застаріло, якщо клас не має #[\AllowDynamicProperties] (або не успадковує типи на кшталт stdClass, де це дозволено). Краще оголосити властивості, використати WeakMap для зовнішніх метаданих або явні __get/__set.

Часткові callables

Форми, які приймає лише call_user_func(), а не виклик $callable() — наприклад "self::method", "parent::method", певні масивні форми — застарілі. Нормалізуйте до Foo::bar або [Class::class, 'method'].

Інтерполяція рядків

Стиль "${var}" / "${expr}" застарілий; використовуйте "{$var}" або конкатенацію.

Інше

  • utf8_encode / utf8_decode: deprecated (краще mb_convert_encoding або iconv).

Розширення та runtime

  • OpenSSL: підтримка AEAD chacha20-poly1305, де доступно в збірці.
  • OCI8: налаштування prefetch для LOB через INI та oci_set_prefetch_lob() на підтримуваних версіях Oracle.
  • DBA (LMDB): прапорці для поведінки з підкаталогами під час створення файлів БД.

Підсумок

PHP 8.2 вигідний командам, які явно описують модель даних: readonly-класи, точніші типи, менше випадкових витоків через #[\SensitiveParameter], а deprecation підштовхує до оголошених властивостей і сучасних callables. Окремо закладіть час на перевірки рядків і локалі (ASCII case у базових функціях), timezone, open_basedir + glob та інтеграційні тести ODBC/PDO_ODBC після змін екранування в DSN.