PHP 8.6 introduces Partial Function Application (PFA). The feature is currently in beta, with a planned release around November 19, 2026.
PHP 8.1 introduced First-Class Callable Syntax, which turns an existing function into a callable with syntax such as `trim(...)`. This works with APIs such as `array_map()`. First-class callables do not bind selected arguments. PFA fills that gap by turning an expression such as `str_replace(' ', '-', ?)` into a callable that accepts the remaining value.
The `?` placeholder represents exactly one argument supplied later. Several placeholders are allowed, and they can appear among fixed positional or named arguments. PFA follows a fixed order: positional values and placeholders come first, named arguments follow, and at most one trailing `...` can appear at the end. The ellipsis leaves all remaining argument slots open.
PFA is designed for callback-heavy code. An `array_map()` call can pass `str_replace('hello', 'hi', ?)` directly as its callback. With `array_filter()`, `mode: ?` can remain open while `is_numeric(...)` fixes the callback and a trailing `...` leaves the array argument for the later call. The resulting callable accepts either positional values such as `0` and `[1, 'a', 2, 'b', 3]`, or named arguments such as `mode: 0` and `array: [1, 'a', 2, 'b', 3]`.
The ellipsis also supports deferred execution. A callable created from `printf('Hello, %s!' . PHP_EOL, ...)` can be invoked later when the greeting is needed. PFA works with the pipe operator, where `str_replace(' ', '-', ?)` receives the value passed through the pipeline. Static and instance methods support the same mechanism. The examples use `Book::create(category: Category::THRILLER, title: ?)` and `$book->publish(new DateTimeImmutable(), ...)`.
Fixed arguments are evaluated when the partial callable is created. In the example with `getPrefix()`, the function prints `Called!`, returns `PHP`, and runs during creation. The returned value is captured for later calls such as `$partial('Alice')` and `$partial('Bob')`. A regular closure evaluates an expression such as `getPrefix()` when each invocation runs.
PFA creates a new closure. It does not preserve all metadata from the original callable. Custom attributes such as `#[MyAttribute]` are dropped, while `#[NoDiscard]` and `#[SensitiveParameter]` are exceptions. `#[SensitiveParameter]` remains available when its parameter stays open. Reflection code must account for these differences. The article also notes that some special constructs are unsupported, without listing them.




Comments
No comments yet — be the first.
Open the discussion
No account or password needed — just enter your e-mail and we’ll send you a one-time sign-in link. First time here? You’re set up automatically.
Your rating will be applied automatically after you sign in.
Check your inbox
We’ve sent a sign-in link to …. Open it on this device — this tab will sign you in automatically.
Nothing arrived? Check your spam folder — and mark the mail as "Not spam" so it lands in your inbox next time.