PHP 8.5 Review
PHP 8.5 is a solid release.
Not because it changes everything, but because it adds a few genuinely useful features, some operational improvements, and a manageable set of migration annoyances.
What Is New in PHP 8.5
The important additions are:
- pipe operator
|> - built-in URI extension
clone()with property updates#[\NoDiscard]- closures and first-class callables in constant expressions
array_first()andarray_last()get_error_handler()andget_exception_handler()- fatal errors now include a backtrace
The pipe operator is the most visible syntax change:
$slug = $title
|> trim(...)
|> (fn($v) => str_replace(' ', '-', $v))
|> strtolower(...);
It is not a speed feature by itself, but it makes “take value, transform, transform again” code much easier to read.
The new URI extension is also genuinely useful. Anywhere you deal with redirects, canonical URLs, feed URLs, API callbacks, or tracking links, it is cleaner than doing everything with parse_url() plus hand-made string surgery.
clone() with property updates is useful for immutable-ish objects and readonly classes. array_first() and array_last() are small additions, but they remove ugly noise.
What Is Actually Good for Performance
The honest answer is: not that much automatically.
According to Tideways' benchmark, real application throughput on modern frameworks is generally very close to 8.4. So PHP 8.5 is not a magic “upgrade and get big free speed” release.
The more interesting performance-related changes are these:
Persistent cURL share handles
This is the most practically useful one.
PHP 8.5 can now reuse DNS, connection, and SSL handshake information across requests for cURL calls. If your app talks to external services a lot, this can cut repeated connection setup overhead.
That matters on integration-heavy stacks much more than tiny syntax-level optimizations.
OPcache is now always built in
In PHP 8.5, OPcache is a required extension. You can still disable it in config, but you can no longer accidentally run a PHP build without it.
Some smaller engine wins
There are also a few smaller improvements:
- optimized
$array === []checks - fewer opcodes for some
match (true)cases - some core functions got tuned, including
array_filter(),array_reduce(),implode(), andusort()
Nice to have, but not the headline.
What Got Deprecated or Changed
Some 8.5 deprecations and behavior changes that are likely to show up in older codebases:
- non-canonical casts like
(integer),(boolean),(double),(binary)are deprecated - backticks as alias for
shell_exec()are deprecated __sleep()and__wakeup()are soft-deprecated in favor of__serialize()and__unserialize()- using
nullas an array offset or inarray_key_exists()is deprecated curl_close()andcurl_share_close()are deprecated because they have effectively been no-ops since PHP 8.0xml_parser_free()is deprecated for the same reason- custom output buffer handlers that emit output now trigger a deprecation
- warnings now appear for some float-to-int casts and
NANcasts
There are also a few operational gotchas:
- if you still load OPcache manually with
zend_extension=opcache.so, PHP 8.5 will warn because OPcache is already built in disable_classesis gone
Common Migration Problems from PHP 8.2 or 8.3 to 8.5
If you jump from 8.2 or 8.3 straight to 8.5, you are effectively taking the accumulated 8.4 and 8.5 changes together.
The most common issues are usually these:
1. Old cast style in legacy code
This one is boring but common:
(integer) $value;
(boolean) $flag;
These should be changed to:
(int) $value;
(bool) $flag;
Easy to bulk-fix, but older Magento modules and legacy libraries still contain this style.
2. Old cURL cleanup code
A lot of old code still ends with:
curl_close($ch);
That is now deprecated. On PHP 8+ these handles are objects and are cleaned up by scope rules.
3. XML parser cleanup leftovers
Same story for:
xml_parser_free($parser);
If your codebase still has it, it is probably just dead legacy cleanup.
4. null passed where arrays or offsets are expected
This tends to show up in sloppy data-handling code, especially around optional config, unserialized payloads, or old helper methods.
Example shape of problem:
array_key_exists($key, null);
or code that assumes null['x'] is acceptable behavior somewhere in a chain.
That now produces deprecation noise and usually points to a real data-shape bug.
5. Output buffering callbacks doing too much
If you have custom ob_start() handlers that print or echo from inside the handler, PHP 8.5 now complains.
That pattern was always sketchy. Now it is loudly sketchy.
6. Serialization hooks still living in the past
If older libraries rely on __sleep() / __wakeup(), they may not fail immediately, but they are now on the wrong side of the language direction.
7. Environment config still assumes older PHP packaging
This is the ops version of migration pain:
- stale
zend_extension=opcache.so - assumptions around optional OPcache packaging
- custom CLI/build scripts using removed or outdated flags
These do not always break the app, but they create noisy deploys and confusing warnings.
A Good Migration Checklist
If you are moving from 8.2 or 8.3 to 8.5, this is the short version:
- Run the test suite with deprecations visible.
- Grep for
(integer),(boolean),(double),(binary). - Grep for
curl_close,curl_share_close,xml_parser_free. - Audit serialization hooks:
__sleep()and__wakeup(). - Check bootstrap and container config for stale OPcache loading.
- Review places where
nullcan reacharray_key_exists(), array offsets, or destructuring. - Upgrade dependencies before blaming PHP itself.
That last one matters a lot. Most migration pain is not core PHP. It is old vendor code.
What About Magento 2?
As of April 24, 2026, Adobe's official system requirements page shows:
- Adobe Commerce 2.4.9-beta1 supports PHP 8.5 and 8.4
- Adobe Commerce 2.4.8-p4 supports PHP 8.4 and 8.3
So for Magento shops, PHP 8.5 is real, but support is still tied to the newer Commerce line. The PHP migration itself is only half the work. The other half is extension compatibility.
Bottom Line
PHP 8.5 is worth adopting, but for normal reasons:
- cleaner syntax
- better URL handling
- more useful runtime/debugging behavior
- smarter cURL behavior for integration-heavy apps
- a manageable migration surface
Just do not sell it internally as a pure performance upgrade. Sell it as a tidy release with a migration checklist.