Skip to main content

PHP 8.5: what is new and when to upgrade

PHP · 09.11.2026 · 6 min read

Why read about PHP 8.5 right now

On 31 December 2026, a month and a half from now, all support for the 8.2 branch ends, and active support for 8.4 ends too: only security fixes remain, until 31 December 2028. If your site runs on 8.2, the question is not whether to move but where to. The dates come from the php.net/supported-versions page.

BranchReleasedActive support untilSecurity fixes until
8.28 December 202231 December 202431 December 2026
8.323 November 202331 December 202531 December 2027
8.421 November 202431 December 202631 December 2028
8.520 November 202531 December 202731 December 2029

For a new project choose 8.5: its security support runs until 31 December 2029. Branch 8.3 lasts until 31 December 2027 and works as a stopgap if your dependencies are not ready for 8.5. Branch 8.1 has not been supported at all since 31 December 2025 (php.net/eol.php). The current 8.5 patch according to the php.net changelog is 8.5.12 of 22 October 2026 (as of early November 2026); check the number before you upgrade.

What is new in PHP 8.5

PHP 8.5 came out on 20 November 2025. Its headline items are the pipe operator, the NoDiscard attribute, cloning with changed properties and two long-awaited array helpers. Everything listed below is confirmed by the UPGRADING file of the PHP-8.5 branch and the php.net release page.

  • the pipe operator |>;
  • the #[\NoDiscard] attribute and the (void) cast;
  • closures and first-class callables in constant expressions;
  • clone with a parameter (clone with);
  • the URI extension, which is now always enabled;
  • array_first() and array_last();
  • persistent cURL share-handles;
  • stack traces on fatal errors;
  • get_error_handler() and get_exception_handler();
  • OPcache, which is now always built in.

The pipe operator

The |> operator passes the result of its left side to the callable on the right, so a chain of transformations reads left to right instead of inside out. The right side is a callable that takes one argument: a function, a method or a first-class callable. Wrap an arrow function in parentheses.

$slug = "  Hello PHP 8.5  "
    |> trim(...)
    |> strtolower(...)
    |> (fn(string $s): string => str_replace(" ", "-", $s));

echo $slug; // hello-php-8.5

Without the pipe the same thing would be written as nested calls: str_replace(" ", "-", strtolower(trim($s))). You have to read that form from the end.

NoDiscard, clone with and array_first()

Three small additions that show up most in everyday code. The #[\NoDiscard] attribute makes PHP warn when the result of a call is ignored, and the (void) cast says explicitly "I do not need the result". clone accepts an array of properties, while array_first() and array_last() replace workarounds such as reset() and end().

#[\NoDiscard]
function saveOrder(array $data): bool { return true; }

saveOrder($data);         // warning: result ignored
(void) saveOrder($data);  // explicit: result not needed

$moved = clone($address, ["city" => "Kyiv"]);
$first = array_first([10, 20, 30]); // 10
$last  = array_last([10, 20, 30]);  // 30

For an empty array array_first() returns null. The previous version is covered in the article on PHP 8.4, and strict typing, which pairs well with NoDiscard, is described in the article on strict_types.

Extensions and environment: URI, cURL, OPcache

Some of the novelties concern the environment rather than the language, and for hosting they matter more than syntax. The URI extension is always enabled and provides the classes Uri\Rfc3986\Uri and Uri\WhatWg\Url for parsing addresses by the standards. Persistent cURL share-handles are created by curl_share_init_persistent(). Stack traces on fatal errors are switched on by the fatal_error_backtraces setting. OPcache is now always built into PHP.

What actually breaks working code

Code is broken not by deprecated features but by the backward incompatible changes section of UPGRADING: deprecated features only raise E_DEPRECATED warnings. For hosting, the items below matter; check them before switching versions, not after an error appears in the log.

  • the disable_classes INI directive is removed: delete it from php.ini and from FPM pools;
  • the zend_extension=opcache line now raises a warning, because OPcache is built in;
  • the values of the constants PDO::FETCH_GROUP, PDO::FETCH_UNIQUE, PDO::FETCH_CLASSTYPE, PDO::FETCH_PROPS_LATE and PDO::FETCH_SERIALIZE have changed: numbers used in place of constants must be replaced;
  • the intl extension requires ICU 57.1 or newer;
  • a $_SESSION key containing the | character raises a warning;
  • casting NAN and out-of-range float values to int raises a warning.

The list is not exhaustive: read the backward incompatible changes section of UPGRADING in full.

Deprecated: what shows up in old code

Deprecated features keep working but raise E_DEPRECATED and may be removed later. Four turn up most often in old code: the casts (boolean), (integer) and (double), backticks instead of shell_exec(), the function curl_close() and null as an array key. The list comes from the Deprecated Functionality section of UPGRADING.

DeprecatedReplace with
(boolean), (integer), (double)(bool), (int), (float)
backticksshell_exec()
curl_close()drop the call, the handle is freed on its own
null as an array keyan explicit key, for example an empty string

When and how to upgrade

Move to 8.5 once your project dependencies declare support for it; if you are on 8.2, do it before the end of December. Do not change the version of a live site in place: install a second version alongside, run the tests and switch the pool.

  1. On a copy of the site, turn on all error output and collect the log on the current version.
  2. Install 8.5 next to the working version, as described in the article on several PHP versions on one server.
  3. Go through the list of incompatible changes and look for them in configs and code.
  4. Update Composer dependencies and run the tests on 8.5.
  5. Switch one FPM pool or one site and watch the log.
  6. Keep the previous version installed for as long as a rollback might need it.
php -v
grep -rn "disable_classes" /etc/php/
grep -rn "zend_extension" /etc/php/
grep -rnE "\((boolean|integer|double)\)" --include=*.php .
grep -rn "curl_close" --include=*.php .

How to keep receiving security fixes for the installed branch is described in the article on updating PHP on Ubuntu and Debian.

Frequently asked questions

Do I need to leave PHP 8.2 before the end of the year?

Yes. On 31 December 2026 support for the 8.2 branch ends, security fixes included. After that date vulnerabilities in it will no longer be fixed.

Is PHP 8.4 acceptable if 8.5 is too early?

For a while: active support for 8.4 ends on 31 December 2026, and security fixes continue until 31 December 2028. For a new project 8.5 is the wiser choice.

Will deprecated functions break my site?

No, they only raise warnings. Code is broken by the items in the incompatible changes section: the removed directive, the changed constants, the ICU requirement.

What should ZevsHost customers do?

On shared hosting the panel switches the PHP version and there is no server to update: pick the version for your site and check the log. On a VPS or dedicated server you choose the version and the updates yourself.

Was this article helpful?
← Back to Knowledge Base Ask Support