PHP's annual release is just around the corner! PHP 8.6 will be released on November 19, 2026. PHP 8.6 is in beta now, with a feature freeze on September 22 and the first release candidate two days later:
#Release Timeline
The PHP 8.6 preparation page has the following timeline for the release:
- Alpha 1 through Alpha 3: July 2 to July 30, 2026
- Beta 1 (soft feature freeze): August 13, 2026
- Beta 3: September 10, 2026
- Feature freeze: September 22, 2026
- RC 1: September 24, 2026
- RC 4: November 5, 2026
- GA: November 19, 2026
The release managers are Daniel Scherzer, Matteo Beccati, and Joe Ferguson.
#Partial Function Application
Partial function application (PFA) lets you call a function with some arguments filled in and get back a closure that takes the rest. The ? placeholder marks a single argument to fill later, and ... stands in for all remaining arguments:
$makeSlug = str_replace(' ', '-', ?);
$makeSlug('Hello World'); // Hello-World
$titles = array_map(strtolower(?), $titles);
The resulting closure keeps the parameter names, types, and defaults of the original function. Arguments you supply are evaluated when the partial is created, not when it is called. A follow-up RFC settled that every ? placeholder becomes a required parameter on the closure, even if the original parameter was optional.
An earlier version of this proposal was declined in 2021. The v2 RFC passed 33 to 0.
#The clamp() Function
The new clamp() function returns the value if it falls within the bounds, or the nearest bound if it does not:
clamp(10, min: 0, max: 100); // 10
clamp(101, min: 0, max: 100); // 100
clamp(-1, min: 0, max: 100); // 0
It works with any comparable type, including strings and DateTime objects. Passing a $min greater than $max throws a ValueError. This replaces the common min(max($value, $min), $max) pattern, which is easy to get backwards.
#A Duration Class
PHP 8.6 adds Time\Duration, a final readonly class that represents a stopwatch-style length of time with nanosecond precision. It has factory methods for each unit, arithmetic methods, and comparison support:
use Time\Duration;
$oneSecond = Duration::fromSeconds(1);
$halfSecond = $oneSecond->divideBy(2);
$total = $oneSecond->add($halfSecond);
$delay = Duration::fromMilliseconds(100)->multiplyBy(2 ** $attempt);
$total > $delay; // comparison operators work
Durations can also be built from an ISO 8601 duration string. The class is intended as a shared type that core functions and the new polling API can accept instead of loose integers and floats. See the Duration RFC for the full method list.
#Readonly Property Defaults
Starting in PHP 8.6, readonly properties can have a default value. Before 8.6 this was a compile-time error, which made it awkward to satisfy get-only interface properties from PHP 8.4 with a fixed value:
final readonly class CreateBooksTable implements Migration
{
public string $name = '2026_01_01_create_books_table';
}
The RFC only removes the restriction. Readonly semantics are unchanged, so the property still cannot be reassigned after initialization.
#DocComments for Function Parameters
Doc comments can now sit directly on a parameter, and ReflectionParameter::getDocComment() returns them. This avoids repeating the parameter name in a @param tag above the function:
function search(
/** Terms to search for in the database */
string $query,
/** Maximum number of entries to return */
int $limit = 10,
): array {
// ...
}
Static analyzers and IDEs can read the comment from the parameter itself. See the parameter DocComments RFC.
#A Polling API
The new Io\Poll namespace gives PHP a unified interface to platform polling mechanisms: epoll on Linux, kqueue on BSD and macOS, event ports on Solaris, and WSAPoll on Windows. It replaces stream_select() for anyone building event loops or async runtimes in userland:
use Io\Poll\{Context, Event, StreamPollHandle};
$poll = new Context();
$server = stream_socket_server('tcp://0.0.0.0:8080');
stream_set_blocking($server, false);
$poll->add(new StreamPollHandle($server), [Event::Read], ['type' => 'server']);
while (true) {
foreach ($poll->wait(1) as $watcher) {
if ($watcher->hasTriggered(Event::Read)) {
// accept the connection
}
}
}
The RFC states the main motivation is internal, such as signal handling and FPM improvements, with userland async frameworks as the secondary audience. See the Polling API RFC.
#SortDirection Enum
A global SortDirection enum with Ascending and Descending cases is now built in. Nothing in core accepts it yet. The RFC proposes it as a shared type so libraries stop defining their own, with query builders given as the example:
$query->orderBy('created_at', SortDirection::Descending);
#Enums Can Implement __debugInfo()
Enums were not allowed to define most magic methods when they shipped in 8.1. PHP 8.6 lifts that restriction for __debugInfo(), since it needs no state, so var_dump() output can be customized:
enum Status: int
{
case Ok = 200;
public function __debugInfo(): array
{
return [__CLASS__ . '::' . $this->name . ' = ' . $this->value];
}
}
#Stream Error Handling
Streams get a unified error model. A new error_mode context option chooses between the current warnings, exceptions, or silence, and stream_last_errors() returns structured StreamError objects for the last operation:
$context = stream_context_create([
'stream' => ['error_mode' => StreamErrorMode::Exception],
]);
try {
$stream = fopen('/nonexistent/file.txt', 'r', false, $context);
} catch (StreamException $e) {
foreach ($e->getErrors() as $error) {
echo $error->code->name . ': ' . $error->message;
}
}
The Stream Error Handling RFC defines more than 50 semantic error codes in a StreamErrorCode enum.
#URI Extension Follow-ups
The URI extension that shipped in PHP 8.5 gains builder classes, so you can assemble a URI without creating intermediate objects for each component:
$uri = new Uri\Rfc3986\UriBuilder()
->setScheme('https')
->setHost('example.com')
->setPath('/foo/bar')
->build();
The follow-up RFC also adds getUriType() and getHostType() methods, plus percent-encoding functions for individual URI components.
#Secure Session Defaults
Three php.ini session defaults change for new installations:
| Setting | Old default | New default |
|---|---|---|
session.use_strict_mode |
0 |
1 |
session.cookie_httponly |
0 |
1 |
session.cookie_samesite |
unset | Lax |
Laravel manages its own session cookies, so most apps are unaffected. Apps that use native PHP sessions and rely on the old defaults should check the session defaults RFC.
#Learn More
- PHP 8.6 preparation tasks and timeline
- PHP RFC index with the full list of RFCs implemented in 8.6
- PHP 8.6 deprecations
Комментарии (0)
Пока нет комментариев — будьте первым.