PHP 8.5: Основни нововъведения

PHP 8.5 продължава линията „повече изразителност в езика“: pipe оператор (|>), #[\NoDiscard] срещу игнорирани връщани стойности и closures в константни изрази за атрибути и default стойности. На платформено ниво — винаги включено URI разширение, по-строг filter и сериозни промени в PDO / Opcache: заложете QA не само за синтаксис, а и за разширения, сборка и INI.

Съдържание


Pipe оператор (|>)

Операторът pipe подава стойността отляво в callable с един параметър отдясно. Удобен е за вериги от трансформации без междинни променливи.

$result = 'Hello World' |> strlen(...);
// Същото като: $result = strlen('Hello World');

Правила, които „хапят“: отдясно трябва да е callable с точно един параметър (и не by-ref). Ако отдясно не е валиден callable — хвърля Error. Arrow functions трябва да са в скоби при |> заради синтактична двусмисленост. Вижте functional operators.

Closures и first-class callable в константни изрази

В PHP 8.5 closures и first-class callable са позволени в константни изрази, включително:

  • аргументи на атрибути;
  • default стойности на свойства и параметри;
  • константи и константи на клас.

Това помага, когато искате метаданни/дефолти да сочат към реален callable, а не към „магически“ низове.

#[\NoDiscard] и (void) cast

#[\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. Полезно за коректно парсване вместо ad hoc низови операции.

Бележки по библиотеки и разширения

  • Filter: FILTER_THROW_ON_FAILURE — при грешка може да се хвърли изключение (не се комбинира с 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" за partitioned cookies.
  • 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, handlers, …)

  • Core: get_error_handler(), get_exception_handler(), Closure::getCurrent()
  • Standard: array_first(), array_last()
  • Reflection, Opcache, PGSQL/SQLite/DOM — вижте 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,
]);

Обратно несъвместими промени (миграционни бележки)

Ядро

  • class_alias(): забранени имена "array" и "callable".
  • Слабо сравнение с bool за „несравними“ обекти — унифицирано с (bool)$object.
  • gc_collect_cycles(): връщаната стойност вече не брои косвено събрани низове/ресурси.
  • Final подкласове: по-гъвкаво заместване на static с self или конкретен клас.
  • Tick handlers: след shutdown, деструктори и output handlers.
  • Трейтове: променен ред на binding спрямо родител.
  • Грешки при компилация/линкване: променен ред на обработка.
  • #[\Attribute] върху abstract class, enum, interface, trait: грешка при компилация, освен ако не се ползва #[\DelayedTargetValidation].
  • disable_classes: премахната INI.
  • Деструктуриране не-масив/не-null с []/list() — предупреждение.
  • int cast извън диапазон и NAN — предупреждения.

Opcache

  • Винаги вграден в бинарника; zend_extension=opcache.so предупреждава. Актуализирайте deployment документация.

PDO

  • Променени числови стойности на PDO::FETCH_* за част от флаговете.
  • FETCH_CLASS ctor args: семантика като call_user_func_array.
  • Ограничения за FETCH_PROPS_LATE, FETCH_INTO + fetchAll() и др.

DOM / SPL / др.

  • Клониране на live NodeList/NamedNodeMapнеуспех.
  • ArrayObject: без enum елементи.
  • mysqli: повторен конструктор → Error.
  • Много места вече хвърлят ValueError вместо TypeError/warnings (напр. Bzip2 bzcompress() диапазони, LDAP invalid option, SNMP хост/порт, sockets портове, FileInfo nul bytes и т.н.) — QA за „входове от потребител“ е задължителен.

Deprecated (чеклист)

Тук е „какво да чистите рано“, преди да стане hard error в следващи версии. Пълен списък: migration85 deprecated.

Core

  • Output в user output handler е deprecated (за да се вижда deprecation-ът, съобщението заобикаля handler-а).
  • Неканонични cast имена (boolean), (integer), (double), (binary) → използвайте (bool), (int), (float), (string).
  • case със ; вместо : е deprecated.
  • Backticks като alias за shell_exec са deprecated.
  • __debugInfo() да връща null е deprecated → върнете [].
  • report_memleaks INI е deprecated.
  • Redeclare на константи е deprecated (и остава warning).
  • Closure binding „аномалии“ (binding на static closure към instance, unbinding $this, rebind scope към internal клас, и т.н.) са deprecated.
  • __sleep() / __wakeup() са soft-deprecated → мигрирайте към __serialize() / __unserialize().
  • null като array offset или към array_key_exists() е deprecated.
  • Инкрементиране на не-числови низове е deprecated → използвайте str_increment().
  • register_argc_argv derivation от query string за не-CLI SAPIs е deprecated.

Extensions / standard library

  • cURL: curl_close() и curl_share_close() deprecated (handle-ите се освобождават автоматично).
  • FileInfo: finfo_close() deprecated; $context на finfo_buffer() deprecated.
  • GD: imagedestroy() deprecated (GdImage се освобождава автоматично).
  • XML: xml_parser_free() deprecated (XMLParser се освобождава автоматично).
  • Random/strings: някои „старо поведение“ се чисти агресивно — планирайте refactor-и преди 8.6/8.7.

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; log_limit влияе на access log limit.
  • Core: hrtime() на macOS използва препоръчителен API.
  • INI: fatal_error_backtraces, max_memory_limit, ограничения за memory_limit.
  • Opcache: opcache.file_cache_read_only, настройки на JIT, коректно отчитане на памет.
  • Производителност: по-бързи изключения, масивни колбеци, Reflection, SIMD, TAILCALL VM с Clang ≥ 19 — вижте other changes.

Обобщение

PHP 8.5 комбинира по-четим синтаксис и по-строга платформа. Тествайте PDO режими, cookies/session, код със стари close помощници и слабо сравнение обект ↔ bool.