The PHP team released PHP 8.6.0 RC5 on November 5, 2026, the final testing milestone before the stable release, due on November 19. Beyond the long-awaited partial function application, this build also tightens session security defaults, a change that will affect every PHP application on upgrade.
A fifth release candidate ahead of the stable build
RC5 follows RC4, released on October 21, which already patched two critical remote-code-execution vulnerabilities. The PHP 8.6 cycle has stretched across several months of testing: RC2 opened the cycle on September 24 after RC1 was scrapped over a packaging mistake, followed by RC3 in early October and RC4 in late October. The release team stresses that RC5 remains a test build and should not be used in production.
Partial function application and new utility functions
The most talked-about addition is partial function application, based on an RFC that was rejected back in 2021 before returning in a new form that passed unanimously. It lets developers skip arguments using a placeholder token instead of writing an intermediate closure. The language also gains a clamp() function to bound a value within a range, and readonly properties can now declare default values, which was a compile-time error through 8.5.
final class Pricing
{
public readonly float $vatRate = 0.20;
public function clampedDiscount(float $requested): float
{
return clamp($requested, 0.0, 0.30);
}
}
$applyVat = fn (float $amount, float $rate) => $amount * (1 + $rate);
$applyDefaultVat = $applyVat(?, 0.20); // partial application
echo $applyDefaultVat(49.0);
A new subsystem for asynchronous I/O
PHP 8.6 introduces Io\Poll, a unified polling interface built on top of each platform’s native mechanism (epoll on Linux, kqueue on BSD and macOS, WSAPoll on Windows). It ships with classes such as Io\Poll\Context and Io\Poll\Watcher, and existing streams can plug into it through StreamPollHandle. Closures also get a stateless-closure cache, and array_map() used with a first-class callable now compiles down to an equivalent foreach loop, skipping intermediate allocations.
Stricter session defaults
The most consequential change for existing applications touches three session-related INI settings, now safer by default.
| Setting | Before 8.6 | From 8.6 | Impact if left unaddressed |
|---|---|---|---|
session.use_strict_mode | 0 | 1 | A custom handler accepting externally supplied, unstored session IDs must implement validateId() or create_sid() |
session.cookie_httponly | 0 | 1 | The session cookie is no longer readable from JavaScript unless explicitly reset to 0 |
session.cookie_samesite | unset | Lax | Cross-site POST requests stop receiving the cookie, unless switched to None alongside cookie_secure=1 |
Three session settings move from a permissive to a restrictive default, with no application code needing to change to benefit.
A few other changes are worth a pass through the UPGRADING file before migrating: many functions now throw a ValueError on a NUL byte in a string argument, and preg_grep() returns false instead of a partial array on a PCRE execution error. Teams that already keep a close eye on their queues, the way Laravel recently reinforced its own queue monitoring, would do well to run their test suite against RC5 now.
Key takeaways
PHP 8.6 enters its final stretch with RC5, released on November 5 ahead of a stable build on the 19th. Partial function application and the Io\Poll API are the most visible additions, but the change that demands real action is the tightened set of session defaults. Teams running custom session handlers or cross-site flows should test now rather than find out in production.
On the projects followed this year, the shift of session.cookie_samesite to Lax is exactly the kind of change that slips through QA and resurfaces three weeks later as a baffling support ticket about a broken webhook or SSO flow. Better to deal with it upfront, calmly, than in a panic on deployment day — Simon Janvier.
Further reading: the official PHP 8.6.0 RC5 announcement on php.net.
