PHP 8.6: частичное применение функций без лишних замыканий

Логотип PHP 8.6 на синем и фиолетовом градиентном фоне

В PHP 8.6 появится Partial Function Application (PFA) — синтаксис, который позволяет зафиксировать часть аргументов вызова и получить готовое замыкание для оставшихся. Это небольшое изменение особенно заметно там, где сегодня приходится писать одноразовые стрелочные функции: в callbacks, преобразованиях коллекций и пайпах.

Что меняется по сравнению с first-class callables

Начиная с PHP 8.1 можно получить ссылку на функцию через запись с многоточием: trim(...). Она уже создаёт Closure, но передать в неё часть значений заранее нельзя. Если нужно заменить пробелы на дефисы, приходится вручную объявлять параметр и прокидывать его дальше.

До PHP 8.6 php
$toSlug = fn (string $value): string => str_replace(' ', '-', $value);

$slugs = array_map($toSlug, $titles);

PFA оставляет в вызове плейсхолдер ?. Он означает: на этом месте аргумент появится позже. Результатом выражения становится Closure с корректной сигнатурой оставшихся параметров.

PHP 8.6: один незаполненный аргумент php
$toSlug = str_replace(' ', '-', ?);

$slugs = array_map($toSlug, $titles);

PFA — это не вызов «наполовину»

Функция в момент создания такой конструкции не выполняется. PHP создаёт обычное замыкание, которое вызовет исходную функцию, когда получит недостающие значения. По смыслу это тот же код, что и стрелочная функция, но без дублирования имён переменных, типов и порядка аргументов.

  • ? резервирует ровно один аргумент; несколько знаков создают несколько параметров замыкания.
  • ... оставляет незаполненными все остальные аргументы и соответствует first-class callable, если других значений нет.
  • Плейсхолдеры можно сочетать с позиционными и именованными аргументами — это удобно, когда нужный параметр находится не последним.
  • PFA работает с функциями, методами объектов, статическими и магическими методами; конструкторы исключены.

Callbacks становятся короче и понятнее

Хороший практический сценарий — адаптировать многопараметричную функцию под API, которое ждёт callback с одним аргументом. Например, заранее задать разрешённые статусы и включить строгое сравнение.

Фильтрация с заранее заданным контекстом php
$allowed = ['new', 'paid', 'shipped'];

$isAllowed = in_array(?, $allowed, strict: true);
$visibleOrders = array_filter($orders, fn ($order) => $isAllowed($order->status));

В данном примере замыкание читается как правило предметной области: «проверить, входит ли переданное значение в разрешённый список». Не нужно искать тело callback, чтобы понять, что в нём зафиксировано.

Самое заметное сочетание — с pipe operator

Оператор |> из PHP 8.5 передаёт значение слева в callable справа. Когда функция принимает дополнительные параметры, раньше приходилось оборачивать её в стрелочную функцию. PFA превращает такую функцию в unary-callable прямо на месте, поэтому цепочка остаётся линейной.

Нормализация строки в PHP 8.6 php
$slug = $title
    |> trim(...)
    |> str_replace(' ', '-', ?)
    |> str_replace(['.', '/', '…'], '', ?)
    |> strtolower(...);

Это не повод превращать любой код в функциональную цепочку. Но для последовательных преобразований данных синтаксис уменьшает шум: хорошо видно и поток значения, и настройки каждой операции.

Именованные аргументы и отложенный запуск

Плейсхолдеры не обязаны стоять в конце. С именованными аргументами можно зафиксировать значения по смыслу, а порядок параметров будущего Closure будет определяться местами ?. Многоточие позволяет передать все оставшиеся параметры позднее — в том числе создать отложенный вызов без аргументов.

Два варианта PFA php
$makeBook = Book::make(
    title: ?,
    category: Category::TECH,
);

$saveReport = saveReport($report, ...);

if ($needsSaving) {
    $saveReport();
}

На что обратить внимание перед использованием

PFA появится только в PHP 8.6, поэтому синтаксис нельзя применять в проектах на более ранней версии: парсер завершит работу до запуска приложения. До обновления PHP используйте привычные Closure и стрелочные функции.

  1. Проверьте минимальную версию PHP во всех окружениях: CI, очередях, CLI и production.
  2. Не используйте ... без необходимости в callback. Он передаёт лишние аргументы дальше, а у функций с необязательными параметрами это может изменить результат.
  3. Не рассчитывайте на PFA для new: частичное применение конструкторов специально не поддерживается.
  4. Оставляйте стрелочную функцию, если ей нужно не просто вызвать другую функцию, а добавить условие, преобразование или несколько действий.

Итог

Partial Function Application не меняет привычную модель PHP и не заменяет замыкания. Она убирает шаблонный код в одном конкретном случае — когда нужно зафиксировать часть аргументов уже существующего callable. В паре с pipe operator это сделает преобразования данных компактнее; в обычном прикладном коде — чуть точнее назовёт намерение.

Источники и ссылки

Все статьи