Skip to main content
← All articles
php

PHP 8.6 lands November 19 — the deprecations are noise, the ValueErrors aren't

PHP 8.6 lands November 19 — the deprecations are noise, the ValueErrors aren't

Everyone's write-up of PHP 8.6 leads with the secure session defaults. I already did one of those. So let me point at the part of the release that will actually interrupt your afternoon: the deprecation list, and — more quietly dangerous — the handful of functions that used to return false and now throw. GA is 19 November 2026. The time to find out what breaks is now, in a throwaway container, not on launch day.

Where it is

PHP 8.6.0 is in release-candidate phase: RC3 landed 8 Oct, RC4 is due 22 Oct, then RC5 on 5 Nov, GA on 19 Nov (dates can still move). The authoritative source for what's changing is the UPGRADING file at the php-8.6.0RC3 tag — read it there, not on some aggregator.

The deprecations (log noise, mostly)

A fat list, and none of it will stop your site — it'll just fill your logs. Deprecated in 8.6: spl_object_hash() (use spl_object_id()), the alias trio is_double()/is_integer()/is_long(), doubleval(), strcoll(), the SORT_LOCALE_STRING flag, metaphone(), spl_classes(); passing an object to http_build_query(), array_walk() and array_walk_recursive(); returning from a finally block; a third argument to define(); and mbregex as a whole, because its Oniguruma engine is no longer maintained. Useful to grep for, not to panic over.

The sneaky ones: false → ValueError

Here's the category I'd actually test. A pile of filesystem and environment functions now throw a ValueError on NUL bytes instead of quietly returning false: file_exists(), is_file(), is_dir(), is_readable(), is_writable(), stat(), filesize(), plus getenv(), putenv(), parse_str() and others. And preg_grep() now returns false instead of a partial array when PCRE fails.

Why that matters more than a deprecation: a deprecation is a log line; a new exception is a 500 if nobody catches it. If some corner of your code does file_exists($somethingUserInfluenced) and that string can carry a NUL byte, the old behavior was a silent false and the new behavior is a fatal unless you wrap it. (My memory is that NUL in these paths has returned false for years — I'm hedging that as recollection; the 8.6 ValueError itself is straight from UPGRADING.) You won't catch this in a unit test that passes clean strings. You catch it by running RC3 against real traffic and reading the logs.

The shiny thing

8.6 also brings genuinely nice additions: partial function application (foo(?, 2) to make a callable with some args fixed — the RFC passed 33–0 and claims performance on par with a hand-written closure), a Time\Duration type, readonly property defaults, and #[\Override] on class constants. My honest take: partial application is cute and I'll reach for it in new code, but most Drupal code won't touch it for years, so it's not a reason to rush the upgrade.

The Drupal reality check

Don't upgrade a Drupal production box to 8.6 on GA day, because Drupal doesn't support it yet — and a green RC test run doesn't change that. Drupal's own PHP 8.6 meta issue (#3608511) is "Needs work": CI already runs 8.6, and they're grinding through breakage — Prophecy's destructor-return deprecation, spl_object_hash() in ReverseContainer (a child issue, fixed and cherry-picked to 11.x on 17 Aug, no release number yet), the session-handler create_sid()/validateId() deprecation, and Guzzle promises using is as a class name. For reference, I grepped my own blog's checkout (core 11.4.2) and found spl_object_hash( on 54 lines across vendor/ and web/core — Guzzle, Symfony's validator and DI and console, Masterminds HTML5, PsySH, plus Drupal's own ReverseContainer and SqlContentEntityStorageSchema. That's a point-in-time snapshot of one checkout, not a verdict; upstream may have fixed several already.

The deprecations tell you what to clean up eventually. The ValueError flips tell you what to test before you ship. Spin up RC3 or RC4 in DDEV or a Docker sidecar, point your real requests at it, and watch the log — that's the whole job.

Links

BM
Blue Moose
The moose behind Blue Moose. Full-stack PHP developer — Drupal by day, Symfony by night, tests always.