PHP 8.6 is scheduled for general availability on 19 November 2026. Feature freeze passed in September and release candidates are in testing, so the feature list is settled. This is a minor release, so existing code keeps working, but it adds several features that will change how everyday PHP code looks.
Here are the changes we think matter most, with examples.
Partial function application
This is the headline feature. You can call a function with some arguments filled in and placeholders for the rest, and PHP returns a closure that waits for the missing values. ? stands for one argument and ... stands for all remaining arguments.
$slug = str_replace(' ', '-', ?);
echo $slug('Hello World'); // Hello-World
$titles = array_map(strtolower(?), $titles);
Until now the same thing needed an arrow function such as fn($s) => str_replace(' ', '-', $s). Combined with the pipe operator added in PHP 8.5, it lets you build data transformations that read top to bottom without temporary variables or wrapper closures.
clamp()
A small function that every codebase has written by hand at some point: keep a value within a range.
clamp(10, min: 0, max: 100); // 10
clamp(101, min: 0, max: 100); // 100
clamp(-1, min: 0, max: 100); // 0
If min is greater than max it throws a ValueError instead of quietly returning something odd, so it is safer than the usual max($min, min($max, $value)).
Readonly properties with default values
Readonly properties can now declare a default value. They still cannot be changed after initialisation, but you no longer need a constructor just to set a fixed value.
final readonly class CreateBooksTable implements Migration
{
public string $name = '2026_01_01_create_books_table';
}
Secure session defaults
For new installations, three session settings change to the values most security guides already recommend:
| Setting | Old default | New default |
|---|---|---|
session.use_strict_mode |
0 | 1 |
session.cookie_httponly |
0 | 1 |
session.cookie_samesite |
not set | Lax |
Two things to note. These are defaults for new installations, so an upgraded server with an existing php.ini keeps whatever it had. Check your configuration rather than assuming. And if your application relies on reading the session cookie from JavaScript, or on cross-site POST requests carrying the session (some older payment callbacks do), test it before rollout.
Better stream error handling
File and network functions such as fopen() have always reported failure through warnings and a false return value. PHP 8.6 adds an error_mode stream context option that can switch to exceptions, plus structured error objects that tell you what actually failed.
$context = stream_context_create([
'stream' => ['error_mode' => StreamErrorMode::Exception],
]);
try {
$handle = fopen('/data/import.csv', 'r', false, $context);
} catch (StreamException $e) {
foreach ($e->getErrors() as $error) {
error_log($error->code->name . ': ' . $error->message);
}
}
That removes a lot of @-suppression and error_get_last() code from import scripts and integrations.
Smaller changes worth knowing
- Time\Duration: an immutable class for elapsed time with nanosecond precision, with factory methods such as
Duration::fromMilliseconds()and arithmetic. Useful for timeouts and retry back-off. - Doc comments on parameters: a doc comment can sit directly above a function parameter and is available through
ReflectionParameter::getDocComment(). Frameworks that generate API documentation or forms from code will use this. - SortDirection enum: a built-in enum with
AscendingandDescendingcases, so libraries can stop defining their own. Core sorting functions do not accept it yet. - Enums can define
__debugInfo()to control whatvar_dump()shows. - URI extension follow-ups: PHP 8.5 added a standards-compliant URI parser. 8.6 adds
Uri\Rfc3986\UriBuilderfor building URIs and helpers for percent-encoding individual parts. - A native polling API in the
Io\Pollnamespace wraps epoll, kqueue and similar system calls. Most applications will never touch it, but async libraries and servers written in PHP will.
Should you upgrade in November?
For most production systems, no, not on release day. Wait for the platform you run on to declare support, and for a patch release or two. Magento, WordPress and the major frameworks usually certify new PHP versions over the following months, and compiled extensions such as Redis, Imagick and ionCube need their own releases.
For new projects and internal tools, starting on 8.6 early in 2027 is reasonable. It will be supported until the end of 2030.
What you should do now is run your test suite against the release candidate in CI. It costs one extra job in your pipeline and tells you months in advance whether anything in your dependencies will block the upgrade.
If you are still on PHP 8.2, the more urgent date is 31 December 2026, when 8.2 stops receiving security fixes. We cover that in our PHP 8.2 upgrade plan.
