Short answer: PHP 8.6 reaches general availability on 19 November 2026, and the same release cycle brings 8.5.13 and 8.4.28 for the branches most production sites actually run. If you host other people's websites, the right move is not to upgrade anyone on day one. It is to make 8.6 available as a choice, keep the current branch as the default, and spend the first weeks watching deprecation notices rather than support tickets. This article covers what is new, which deprecations will show up in your logs, the session defaults that change only for new installations, and a rollout order that does not break customer sites.
What Is Actually New in 8.6
Partial function application
The headline feature. A call can be written with ? in place of an argument, which produces a closure that takes the missing ones:
$slugify = str_replace(' ', '-', ?);
$slugify('hello world'); // hello-world
A ... stands in for all remaining arguments. One detail trips people up: every ? placeholder becomes a required parameter on the resulting closure, even where the original parameter was optional.
clamp()
clamp(101, min: 0, max: 100); // 100
It returns the value when it falls inside the bounds and the nearest bound otherwise. It works with any comparable type, including strings and DateTime objects, and throws a ValueError if the minimum exceeds the maximum. It replaces the max($min, min($max, $value)) idiom that nobody ever reads correctly the first time.
Time\Duration
A final readonly class representing a length of time with nanosecond precision, with factory methods such as Duration::fromSeconds(1), arithmetic through add(), multiplyBy() and divideBy(), comparison support, and construction from ISO 8601 duration strings. For anyone who has stored durations as integer seconds and then argued about which unit a column holds, this is the fix.
Other additions worth knowing
- Readonly properties can have default values, which used to be a compile-time error.
- A polling API in the new
Io\Pollnamespace, built on epoll, kqueue, event ports and WSAPoll, intended to replacestream_select()in event loops and async runtimes. - A built-in SortDirection enum with
AscendingandDescending, so libraries can finally agree on one type instead of each shipping its own. - Structured stream errors: a new
error_modecontext option chooses between warnings, exceptions or silence, andstream_last_errors()returns error objects with semantic codes. - Enums may implement
__debugInfo(), and parameters can carry their own doc comments, readable through reflection.
The Deprecations That Will Fill Your Logs
A new major release does not break code on the first day. It starts writing deprecation notices, and on a busy shared server those notices are the first thing you notice, because they arrive in volume.
The ones to expect in 8.6:
returninside afinallyblock.- Returning a value from a constructor.
- The third argument to
define(). - Long-standing aliases:
is_double,is_integer,is_longanddoubleval. strcoll,metaphone,spl_classesandspl_object_hash.- Several
ArrayIteratormethods, and the CSV methods onSplFileObject.
Before you offer 8.6 to anyone, it is worth knowing which of your customers' code touches these. A single pass over the document roots answers that, and it is quick enough to run on a live server:
grep -rIl --include='*.php' \
-E '\b(is_double|is_integer|is_long|doubleval|strcoll|metaphone|spl_classes|spl_object_hash)\s*\(' \
/home 2>/dev/null | head -50
The result is a list of sites to warn rather than a list of sites that will break. Deprecated is not removed, and these functions still work in 8.6. But a site that logs a deprecation notice on every request will eventually fill a disk, and the operator who finds out from a monitoring alert at 3am would rather have found out from a grep.
The Session Defaults Change, and Who It Applies To
PHP 8.6 ships safer session defaults in its recommended configuration:
| Setting | Old default | New default |
|---|---|---|
session.use_strict_mode | 0 | 1 |
session.cookie_httponly | 0 | 1 |
session.cookie_samesite | unset | Lax |
All three are improvements. Strict mode makes PHP refuse to adopt a session ID it never issued, which closes session fixation. httponly keeps the session cookie away from JavaScript. SameSite=Lax limits when the cookie travels on cross-site requests.
The important operational detail is the scope: these are defaults for new installations. An existing server that is upgraded keeps the php.ini it already has, which means your current settings carry over unchanged and you get none of the benefit automatically. There is no reason to wait for 8.6 to adopt them. The three lines work on every supported branch today:
session.use_strict_mode = 1
session.cookie_httponly = 1
session.cookie_samesite = Lax
Set them, restart PHP-FPM, and test logins on a sample of sites. The one to watch is SameSite=Lax on applications that rely on a third-party site posting a form back into the session, which in practice means some payment callbacks and some single sign-on flows.
Does This Affect a Panelica Server?
A new PHP major release is an opportunity rather than an incident, and the thing that decides whether it stays that way is whether PHP version is a per-site choice or a server-wide one.
On Panelica it is per site. Each domain and subdomain carries its own PHP version, each account's sites run in their own PHP-FPM pool under their own system user, and changing a site's version is a panel setting rather than a server migration. PHP 8.1, 8.2, 8.3, 8.4 and 8.5 are available as panel packages, built from source with their extensions, and legacy branches from 5.6 to 7.4 remain available for applications that genuinely cannot move. That combination is what makes a major-version transition boring: you move one site, you look at it, and you move the next one.
It also means you are not forced to choose between an old application and a current PHP for everything else on the server. The customer with a 2014 codebase keeps their branch, while the rest of the server runs something modern.
If PHP version is currently a server-wide decision in your environment, that is the constraint worth removing before November, not after. See how Panelica runs multiple PHP versions side by side.
A Rollout Order That Does Not Break Anything
- Take the patch releases first. 8.5.13 and 8.4.28 are the ones that matter for sites already in production. Security and bug fixes on your current branch carry no migration risk and should not wait for a decision about 8.6.
- Add 8.6 as an option, change no defaults. New installations and developers who ask for it get it. Nobody is moved.
- Move your own sites first. Your marketing site, your status page, your internal tools. If you host, you have test subjects that do not generate support tickets.
- Run the deprecation grep and contact the owners of what it finds. A short, specific message naming the file and the function is worth more than a general announcement nobody reads.
- Check extensions before promising anything. A major PHP release is always ahead of some third-party extensions. Loaders, APM agents, and anything that ships a compiled binary need their own 8.6 build to exist. Confirm with
php -mon a test site rather than with a vendor's roadmap page. - Change the default for new accounts only when the first five steps are quiet. Existing sites keep their version until their owner moves them. There is no deadline that justifies moving somebody's working site on your schedule.
Frequently Asked Questions
When is PHP 8.6 released?
19 November 2026 is the general availability date for PHP 8.6.0. PHP ships one new minor release every November, and release candidates ran through the preceding weeks; the final release candidate shipped alongside candidates for 8.5.13 and 8.4.28.
Should I upgrade my production sites to PHP 8.6 immediately?
No. Make it available, test with your own sites, and let application owners move when their stack is ready. The releases to apply promptly are the patch versions on your current branch, 8.5.13 and 8.4.28, which carry fixes without migration risk.
What is partial function application in PHP 8.6?
A syntax for creating a closure from an existing call by leaving arguments out with ?, for example str_replace(' ', '-', ?), with ... standing in for all remaining arguments. Each ? becomes a required parameter of the resulting closure, even if the original parameter was optional.
Will PHP 8.6 break my existing code?
Deprecations are notices, not removals, so deprecated functions still work in 8.6. The practical risk is log volume on busy sites and third-party extensions that do not yet have an 8.6 build. Check loaded extensions with php -m on a test site before moving anything that depends on one.
Do the new session security defaults apply when I upgrade?
No. They are defaults for new installations. An upgraded server keeps its existing php.ini. You can adopt all three today on any supported branch by setting session.use_strict_mode = 1, session.cookie_httponly = 1 and session.cookie_samesite = Lax, then restarting PHP-FPM.
Which functions are deprecated in PHP 8.6?
Among others: is_double, is_integer, is_long, doubleval, strcoll, metaphone, spl_classes and spl_object_hash, several ArrayIterator methods, and the CSV methods on SplFileObject. Returning a value from a constructor, using return inside finally, and the third argument to define() are also deprecated.
Can I run different PHP versions for different websites on one server?
Yes, and for a hosting server it is the only arrangement that scales. On Panelica each domain and subdomain has its own PHP version and its own PHP-FPM pool running as the account's system user, with versions 8.1 through 8.5 available as panel packages and legacy branches from 5.6 to 7.4 available for applications that cannot be moved.