PHP 8.5: Головні нововведення
PHP 8.5 продовжує лінію «більше виразності в мові»: оператор конвеєра (|>), #[\NoDiscard] проти ігнорування повернених значень і замикання в константних виразах для атрибутів і значень за замовчуванням. На рівні платформи — завжди увімкнене URI-розширення, суворіший filter і суттєві зміни PDO / Opcache — закладайте час на QA не лише для синтаксису, а й для розширень, збірки та INI.
Зміст
- Оператор конвеєра (
|>) - Замикання та first-class callable у константних виразах
#[\NoDiscard]і приведення(void)- Розширення URI (RFC 3986 / WHATWG URL)
- Оновлення бібліотек і розширень
- Нові функції (
array_first,array_last, обробники, …) - Практичні рецепти
- Зворотно несумісні зміни (міграційні нотатки)
- Deprecated (чеклист)
- Інші зміни та експлуатація (Opcache, INI, продуктивність)
Оператор конвеєра (|>)
Оператор pipe передає значення зліва в callable з одним параметром справа. Зручний для ланцюгів перетворень без тимчасових змінних.
$result = 'Hello World' |> strlen(...);
// Те саме: $result = strlen('Hello World');
Правила, які “кусаються”: праворуч має бути callable рівно з одним параметром (і не by-ref). Якщо праворуч не вийде валідний callable — буде Error. Arrow functions у парі з |> потрібно брати в дужки через синтаксичну неоднозначність. Деталі — у functional operators.
Замикання та first-class callable у константних виразах
У PHP 8.5 замикання та first-class callable дозволені в константних виразах, зокрема:
- аргументи атрибутів;
- значення за замовчуванням для властивостей і параметрів;
- константи та константи класу.
Практично це зручно, коли метадані/дефолти мають посилатися на реальний callable, а не на “магічні” рядки.
#[\NoDiscard] і приведення (void)
#[\NoDiscard] позначає функції/методи, чиє повернене значення небажано ігнорувати.
(void) явно означає «відкидаю навмисно». Само по собі не змінює runtime, але може приглушити попередження, пов’язані з #[\NoDiscard], і допомагає статичному аналізу.
#[\NoDiscard]
function loadConfig(): array { return []; }
(void) loadConfig();
Практичний підхід: позначайте результати, які легко “забути” використати (builder-и, валідатори, методи, що повертають bool/Result), щоб виклики без перевірки не проходили непоміченими.
Розширення URI (RFC 3986 / WHATWG URL)
У PHP 8.5 додано завжди увімкнене розширення uri для URI/URL за RFC 3986 і моделлю WHATWG URL. Корисно для коректного парсингу замість ручного substr на користувацькому вводі.
Оновлення бібліотек і розширень
- Filter: прапор
FILTER_THROW_ON_FAILURE— при помилці валідації можна отримати виняток замістьfalse(не поєднується зFILTER_NULL_ON_FAILURE). - Intl: наприклад
IntlListFormatter,Locale::addLikelySubtags()/minimizeSubtags(), додаткові константи стилівNumberFormatterдля валют (залежить від ICU). - Session / cookies:
session_set_cookie_params(),session_get_cookie_params(),session_start(),setcookie()/setrawcookie()— підтримка partitioned cookies через ключ"partitioned". - Standard:
mail()з sendmail повертає реальні помилки;getimagesize()— HEIF/HEIC, SVG (за наявності libxml), додаткові поля одиниць вимірювання розмірів. - DOM: наприклад
Dom\Element::$outerHTML, властивість$childrenуDom\ParentNode. - cURL: нові ключі/опції для
curl_getinfo/curl_setopt(часто залежать від версії libcurl).
Нові функції (array_first, array_last, обробники, …)
- Core:
get_error_handler(),get_exception_handler(),Closure::getCurrent() - Standard:
array_first(),array_last() - Reflection, Opcache, драйвери — див. new functions
Практичні рецепти
Pipe-ланцюжок для нормалізації
$slug = $raw
|> trim(...)
|> strtolower(...)
|> preg_replace('/\s+/', '-', ...);
Filter з винятком замість false
$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT, FILTER_THROW_ON_FAILURE);
Перший/останній елемент без ручної індексації
$first = array_first($list);
$last = array_last($list);
Partitioned cookies (де це доречно)
setcookie('sid', $sid, [
'path' => '/',
'secure' => true,
'httponly' => true,
'samesite' => 'None',
'partitioned' => true,
]);
Зворотно несумісні зміни (міграційні нотатки)
Ядро мови / runtime
class_alias(): заборонені імена"array"та"callable".- Нестроге порівняння з bool для «непорівнюваних» об’єктів — уніфіковано з
(bool)$object. gc_collect_cycles(): повернене значення більше не враховує рядки/ресурси, зібрані опосередковано.- Final-підкласи: гнучкіше заміщення
staticнаselfабо конкретний клас. - Tick handlers: після shutdown, деструкторів і output handlers.
- Трейти: змінено порядок прив’язки відносно батька.
- Помилки компіляції/лінкування: інший порядок обробки.
#[\Attribute]на abstract class, enum, interface або trait: помилка компіляції, якщо не відкладена валідація через#[\DelayedTargetValidation].- INI
disable_classes: видалено. - Деструктуризація не-масиву й не-
nullчерез[]/list(): попередження. - Приведення до int поза діапазоном і NAN: попередження.
Opcache
- Opcache завжди вбудований у бінарник;
zend_extension=opcache.so/.dllдає попередження. Оновіть документацію deployment.
PDO (високий ризик)
- Змінені числові значення
PDO::FETCH_*для ряду прапорів. - Аргументи конструктора для
FETCH_CLASS: семантика як уcall_user_func_array. - Обмеження на
FETCH_PROPS_LATE,FETCH_INTOзfetchAll()тощо.
DOM / SPL / інше
- Клонування живих
NodeList/NamedNodeMap→ помилка. ArrayObject: не приймає enum як елементи.- mysqli: повторний виклик конструктора на вже створеному об’єкті → Error.
- У багатьох розширеннях з’являються
ValueErrorтам, де раніше булиTypeError/warnings або тихе падіння (Bzip2 діапазони вbzcompress(), LDAP invalid option, SNMP host/port, sockets порти, FileInfo nul bytes тощо) — перевіряйте “користувацькі входи” тестами.
Deprecated (чеклист)
Це “що краще почистити завчасно”, перш ніж стане hard error у наступних версіях. Повний список: migration85 deprecated.
Core
- Вивід усередині user output handler — deprecated (повідомлення обходить handler, щоб бути видимим).
- Неканонічні назви кастів
(boolean),(integer),(double),(binary)→ використовуйте(bool),(int),(float),(string). caseіз;замість:— deprecated.- Backticks як alias для
shell_exec— deprecated. __debugInfo()повертаєnull— deprecated → повертайте[].report_memleaksINI — deprecated.- Redeclare констант — deprecated (і надалі warning).
- “Проблеми binding-у closure” (binding instance до static closure, unbind
$this, rebind scope до internal класу тощо) — deprecated. __sleep()/__wakeup()— soft-deprecated → переходьте на__serialize()/__unserialize().nullяк array offset або вarray_key_exists()— deprecated.- Інкремент нечислових рядків — deprecated → використовуйте
str_increment(). - Derivation
$_SERVER['argc']/argvіз query string для не-CLI SAPIs — deprecated (register_argc_argv).
Extensions / standard library
- cURL:
curl_close()іcurl_share_close()deprecated (handles звільняються автоматично). - FileInfo:
finfo_close()deprecated;$contextуfinfo_buffer()deprecated. - GD:
imagedestroy()deprecated. - XML:
xml_parser_free()deprecated.
PDO
uri:DSN — deprecated (ризики при remote URIs).- Driver-specific константи/методи в базовому
PDO— deprecated → використовуйтеPdo\\*класи (Pdo\\Mysql::...,Pdo\\Pgsql::..., тощо).
Інші зміни та експлуатація
- CLI:
--ini=diff;cli_set_process_title()падає, якщо заголовок занадто довгий (без тихого обрізання). - FPM:
fastcgi.script_path_encodedдля керування decoding script path при ProxyPass; access log limit враховуєlog_limit. - Core:
hrtime()на macOS використовує рекомендований API. - INI:
fatal_error_backtraces,max_memory_limit, обмеження наmemory_limitу runtime. - Opcache:
opcache.file_cache_read_only, налаштування JIT, коректне повідомлення про пам’ять. - Продуктивність: швидше створення винятків, колбеки по масивах, Reflection, SIMD, TAILCALL VM з Clang ≥ 19 — other changes.
Підсумок
PHP 8.5 поєднує зручніший синтаксис і суворішу платформу. Після оновлення перевірте режими PDO, cookie/session, код із застарілими close-хелперами та старе нестроге порівняння об’єктів із bool.