PHP 8.6 RC5 Is the Final Test: Fix These Before Nov 19

PHP 8.6 RC5 Is the Final Test: Fix These Before Nov 19

PHP 8.6 RC5 Is the Final Test: Fix These Before Nov 19

PHP 8.6.0 RC5 is out, and this one is different from the earlier release candidates. It is the final RC before the stable release on 19 November 2026 — just 13 days away.

That means the features are frozen. Nothing new will be added now. What is left is testing, and this is the best week to do it: if you find a problem now, there is still time to fix it calmly. If you find it on 19 November, in production, there is not.

A quick note so this does not repeat our earlier coverage: we already walked through the headline features on 7 October (RC3) and again on 21 October — partial function application, clamp(), Time\Duration, and the safer session defaults. This article is the other half: the deprecations, the small breaking changes, the speed wins, and a short checklist to run on your Laravel app before the release lands.

And one rule first: do not use RC5 in production. It is test software, not a stable release. Test it on your laptop or staging, never on a live site.

1. The timeline, in short

Milestone Date
RC5 (final RC) 5 November 2026
PHP 8.6.0 stable 19 November 2026
PHP 8.2 security support ends 31 December 2026

RC5 also carries the fixes for the two critical remote-code-execution flaws from 21 October (CVE-2026-109618 and CVE-2026-109619, both rated CVSS 9.2). If you are still on an unpatched PHP 8.4 or 8.5, patch that first — that is urgent, and it is separate from the 8.6 upgrade.

2. The deprecations to fix now

A deprecation is not an error. Your code still runs, but PHP shows you a notice that says: change this before PHP 9. The ones below are the ones a normal Laravel codebase is most likely to hit.

Old code Use instead
is_integer() / is_long() is_int()
is_double() / doubleval() is_float() / floatval()
spl_object_hash() spl_object_id()
return $value; inside __construct() return nothing
return inside a finally block restructure the code, do not return from finally
mb_ereg*() functions preg_*() functions

Two of these deserve a little more attention.

First, spl_object_hash(). A lot of older packages use it as a quick object ID. In PHP 8.6 it is deprecated, and spl_object_id() is the replacement. Your own code may be clean, but a package in your vendor/ folder may not be. After you switch to 8.6 on staging, watch your logs for this one.

Second, returning a value from a constructor. It never really did anything useful — the value was thrown away — so PHP is now telling you to stop. Same for returning from a finally block: it silently swallows exceptions, which is exactly the kind of bug that is hard to find later.

A fast way to find the easy ones in your own code:

grep -rn "is_integer\|is_double\|spl_object_hash\|doubleval" --include="*.php" app/ routes/ config/

Fix what you find, run your tests again, and move on. That is the whole job for most apps.

3. The small changes that can actually break you

Deprecations warn you. These changes do not warn you — they change behaviour. Read this section before you upgrade.

Some functions now throw instead of warning. If you pass a NUL byte in a path to file_exists(), is_file(), filesize() or stat(), or a negative value to sleep(), PHP 8.6 throws a ValueError where older versions only warned you. If your code used to pass bad input and carry on, it will now stop with an exception. That is better in the long run, but test any file-upload or file-path code carefully.

preg_grep() returns false on a PCRE error — for example bad UTF-8 with the /u flag — instead of a partial array. If you loop over its result without checking, add a check.

trim() now also strips form feeds. "\f" joins the default characters of trim(), ltrim() and rtrim(). If you were keeping a form feed at the end of a string on purpose, pass the character list yourself: trim($value, " \n\r\t\v\0").

Session defaults are secure now. This one we covered before, but it is worth repeating because it is the change most likely to break a real app: session.use_strict_mode is now 1, session.cookie_httponly is 1, and session.cookie_samesite is "Lax". Laravel sets its own session cookie behaviour from config/session.php, so most Laravel apps will not feel it — but if your app handles native PHP sessions by hand, or relies on a session cookie surviving a cross-site POST (payment-gateway callbacks are the classic case), test the login and payment flows properly before upgrading.

A few more, quickly: SplFileObject changed how next(), fgets() and current() share the current line, so run your tests if you read files line by line with it. session_encode() returns an empty string for an empty session, not false. And an out-of-memory error now exits with code 134, not 1, so check your process monitor if it watches exit codes.

4. The small new things you will actually use

PHP 8.6 is not only about the big features. Some of the quieter additions are the ones you will reach for first.

JSON errors finally tell you where. When a webhook payload fails to parse, json_last_error_msg() now says something like Syntax error near location 1:25 — the line and column, not just "syntax error". The JsonException from JSON_THROW_ON_ERROR gets the same detail.

Stream errors as real exceptions. file_get_contents() on a missing file used to give you a warning and false. PHP 8.6 can throw a StreamException instead, if you ask for it in the stream context. There are also stream_last_errors() and stream_clear_errors() if you want to read errors without an exception handler.

Build a URI, do not glue strings. PHP 8.5 added URI parsing; 8.6 adds the builder:

$uri = (new Uri\Rfc3986\UriBuilder())
->setScheme('https')
->setHost('laranepal.com')
->setPath('/blog')
->setQuery('page=2')
->build();
 
$uri->toString(); // "https://laranepal.com/blog?page=2"

A SortDirection enum. PHP now ships a global SortDirection enum with Ascending and Descending cases, so your packages can stop inventing their own 'asc' and 'desc' strings. No PHP 8.6 function takes it yet — it is there for your code to use.

Enums can decide what dd() shows. Add a __debugInfo() method to an enum and var_dump() / dump() will show what you return, for example a readable label instead of the raw value.

#[\Override] now works on constants too. The attribute that already guards methods (and, since 8.5, properties) now also checks that a child class constant really overrides a parent one. If the parent constant is renamed, PHP tells you at compile time.

Readonly properties can have defaults. public readonly int $perPage = 15; is now valid. Before 8.6 it was a fatal error, and you had to move the default into the constructor just to make the property readonly.

5. Faster, without changing your code

A few speed wins come free with the upgrade. array_map() with a first-class callable or a partial — like array_map(strtoupper(...), $names) — is now compiled into a plain foreach loop, with no closure created. json_encode() is faster on arrays and objects, and on JSON_PRETTY_PRINT. Stateless closures are cached and reused instead of being created again each time. And the JIT now works on ZTS builds on Apple Silicon, which is the build FrankenPHP uses.

Do not plan your upgrade around a speed number. The measured gain on a real app template was around 3%, and that is a direction, not a promise. The real reason to upgrade is the features and the support window, not the benchmark.

6. Your Laravel upgrade checklist

Do this on staging, in order, and do not skip step 1.

1. Try RC5 in Docker, in one command. You do not need to install anything on your machine:

docker run --rm -it php:8.6-rc-cli php -v

2. Run your full test suite on 8.6. Not just the happy path. Include the file-upload, payment, and login flows. Turn on deprecation logging and read the log when it finishes.

3. Grep for the deprecated functions. The command from section 2, plus a check for mb_ereg and for return inside finally blocks. Fix your own code first, then check whether a package needs an update.

4. Check your Laravel and PHP version pairing. Laravel 13 needs PHP 8.3 to 8.5 today, so do not upgrade production to PHP 8.6 on day one and assume the framework is ready. Wait for the framework's 8.6 support, test the combination on staging, and only then plan the production move.

5. Test sessions and payments. Log in, log out, and run a payment callback end to end. This is where the new session defaults bite, if they bite anywhere.

6. Check your extensions and tools. Confirm your extensions build on 8.6, and remember that PHP-Parser-based tools (including PHPUnit code coverage) may not yet parse the new partial-application ? syntax. Fine in app code you do not measure coverage on; avoid it in covered code until the tooling catches up.

7. If you are still on PHP 8.2, make a separate plan. Security support for PHP 8.2 ends on 31 December 2026. After that there are no more patches, even for critical flaws. Move those projects to 8.4 or 8.5 this quarter, and test 8.6 on the side.

The bottom line

PHP 8.6 is 13 days away, and RC5 is the last chance to test it before it is final. The headline features are already known. The work that matters now is unglamorous: fix a handful of deprecated calls, test the flows that touch files, sessions and payments, and run your test suite once on the release candidate.

Do that this week, while there is still time to fix things calmly, and 19 November becomes a normal upgrade day instead of a fire drill.


Sources

  • Nuno Maduro, "Everything New in PHP 8.6" — timeline (RC5 Nov 5, GA Nov 19), partial function application, Time\Duration, clamp(), readonly defaults, __debugInfo() on enums, #[\Override] on constants, JSON error location, stream errors, Io\Poll, SortDirection, URI builder, performance wins, breaking changes, deprecations. https://nunomaduro.com/posts/everything-new-in-php-8-6
  • Laravel News, "PHP 8.6" tag — PHP 8.6 arrives November 19, 2026 with partial function application, a clamp() function, a Duration class, readonly property defaults, and new deprecations. https://laravel-news.com/tag/php-86
  • PHP.net, Pre-Release Builds — PHP 8.6.0RC5 listed 05 Nov 2026. https://www.php.net/pre-release-builds.php
  • LinuxCompatible, "PHP 8.6.0 RC5 Ships With 8.5.13 and 8.4.28 Candidates Ahead of 19 November GA" — RC5 is the final candidate before GA; all three carry fixes for CVE-2026-109618 and CVE-2026-109619. https://www.linuxcompatible.org/story/php-860-rc5-ships-with-8513-and-8428-candidates-ahead-of-19-november-ga/
  • Earlier LaraNepal coverage (do not repeat): "PHP 8.6.0 RC3 Is Out: What Laravel Devs Need to Know" (2026-10-07) and "PHP Drops a Critical Security Update Today — and PHP 8.6 Lands on November 19" (2026-10-21).
Dinesh Uprety

WRITTEN BY

Senior Software Engineer • Writer @ Laranepal • PHP, Laravel, Livewire, TailwindCSS & VueJS • CEO @ Laranepal & Founder @ laracodesnap

Discussion

Login or register to comment or ask questions

No comments yet

Be the first to share your thoughts or ask a question.

Join the conversation

Sign in to share your thoughts with the community.