PHP 8.6 is scheduled to arrive on November 19, 2026. The version described here combines language changes, new APIs, improved I/O facilities, and stricter defaults. It also deprecates legacy interfaces and ambiguous behavior.

Partial function application lets developers bind selected arguments and receive a closure for the remaining ones. A question mark marks an argument supplied later, while an ellipsis leaves later parameters open. The feature works with PHP's pipe operator and can remove wrapper closures from transformation pipelines.

Arguments used to create a partial function are evaluated immediately. An arrow function evaluates its body on every call, which matters for changing state, time, and request data. Partial application does not support `new`, magic property access through `__get()` or `__set()`, or caller-scope functions such as `extract()` and `func_get_arg()`. It produces an anonymous closure, so the original function name and attributes are not retained as they are with a first-class callable such as `strlen(...)`.

Readonly properties can declare default values. The `#[\Override]` attribute now checks class constants as well as methods and reports an error when the parent class or interface has no matching member. Enums can implement `__debugInfo()`, giving developers control over their representation in functions such as `var_dump()`.

The new `\Time\Duration` class gives time spans an explicit type. It supports factories such as `Duration::fromSeconds(5)` and `Duration::fromMilliseconds(500)`. A duration stores seconds, nanoseconds, and a negative flag. A value of 1500 milliseconds is represented as one second plus 500 million nanoseconds.

Durations can be added, multiplied, and compared directly. They are immutable, so operations return new instances. This model also supports retry delays and exponential backoff while keeping units visible in the code.

PHP 8.6 adds `clamp()`, which restricts a value to a lower and upper bound. It works with numbers and comparable values such as date-time objects. A date after December 31, 2026 can therefore be reduced to that maximum date.

JSON parsing errors gain location information. Existing mechanisms include `json_last_error()`, `json_last_error_msg()`, and `JSON_THROW_ON_ERROR`, which raises `JsonException`. PHP 8.6 can report a position such as `1:3` for a syntax error. This change concerns parsing diagnostics and is separate from the JSON Schema Validation RFC, which addresses application-level structure and content.

The standard `SortDirection` enum defines `Ascending` and `Descending`. Libraries can use the type for sorting configuration, map its cases to SQL `ASC` and `DESC`, and convert an HTTP request parameter before calling a repository.

The default character set removed by `trim()`, `ltrim()`, and `rtrim()` gains the form-feed escape sequence `\f`. Applications that depend on the previous character list should review their string handling during the upgrade.

PHP 8.6 deprecates returning a value from `finally`, because that return can replace a value from `try` or `catch`. A cleanup block may still use a bare `return;`. `spl_object_hash()` is deprecated, with `spl_object_id()` recommended for object identifiers. The replacement returns an integer instead of the old 32-character string. Value returns from `__construct()` and `__destruct()` are also deprecated, while a bare return remains valid for early exit.

The deprecation work also covers `spl_classes()`, legacy type aliases such as `is_double()`, `strcoll()`, and `metaphone()`, object-to-array coercion, and selected identifiers used as class or function names. `let`, `is`, and `readonly` are being reserved for possible future syntax.

Session defaults become stricter. PHP 8.6 sets `session.use_strict_mode = 1`, `session.cookie_httponly = 1`, and `session.cookie_samesite = Lax`. These settings limit attacker-supplied session IDs, block direct JavaScript access to session cookies, and reduce many cross-site request risks. Cross-site authentication flows and applications that read cookies from JavaScript should review their configuration.

The new Polling API provides one interface for platform-specific I/O polling. It can select mechanisms such as `epoll`, `kqueue`, event ports, `WSAPoll`, or `poll`. The existing `stream_select()` function is based on `select()` and remains subject to scalability and platform limitations.

The API uses `Io\Poll\Context`, `Io\Poll\Event`, and `StreamPollHandle` to watch non-blocking streams. A TCP server can register a socket for `Event::Read`, wait with `Context::wait()`, and accept clients when the event fires. The API supplies a low-level waiting mechanism, not a complete asynchronous runtime or event loop. ReactPHP and Amp can build higher-level event-loop abstractions on it.

`Context::wait()` accepts a `Time\Duration` timeout. A zero-second duration checks for events without waiting, `null` waits indefinitely, and durations can express intervals from hours down to nanoseconds. The article uses a 1500-millisecond timeout as an example.

The recommended migration process is incremental: scan, run a dry run, review, apply changes, test, measure, and repeat. PHPCompatibility can find compatibility problems and deprecations in code that tests do not execute. Rector can automate rewrites, provided developers inspect its dry-run diff and verify the covered PHP set. PHPStan with deprecation rules can detect deprecated APIs when its stubs support them, while a baseline tracks the existing backlog. Tests expose runtime warnings on the target version within the paths they execute. CI can reject increases in the deprecation count.

The overall direction is a more expressive PHP language with typed value objects, clearer diagnostics, stronger session defaults, native polling support, and a substantial cleanup list for migration planning.