编程 PHP 8.6 部分函数应用:用 ? 预填参数,少写一层 use 和临时闭包

2026-10-04 21:01:45

PHP 8.6 部分函数应用:用 ? 预填参数,少写一层 use 和临时闭包

PHP 8.6 的 GA 定在 2026-11-19,alpha/beta/RC 铺满全年,节点见官方时间表:。项目主页:。

这一版里跟日常写业务代码关系最近的,是已经投票通过的部分函数应用(partial function application)。

? 占位符做什么

在函数调用里写 ?,表示这个位置的参数先空着,调用表达式本身变成一个闭包:

$replace = str_replace('a', 'b', ?);

$replace('banana'); // 'bbnbnb'

str_replace 的前两个实参在写这一行的时候就固定了,剩下第三个参数留给调用方。产物是一个 Closure,可以直接当 callback 用:

$keys = ['user_id', 'user_name', 'user_email'];

$dashed = array_map(str_replace('_', '-', ?), $keys);

以前这种位置要么现写一个箭头函数,要么写 use 兜住外部变量。

和闭包、一等可调用对象的区别

三种写法产出的都是 Closure,差别在参数从哪来:

// 一等可调用对象(PHP 8.1):整体变成闭包,参数一个都不填
$f = str_replace(...);

// 自己写闭包:参数、类型、默认值都由你声明
$f = fn(string $s) => str_replace('a', 'b', $s);

// 部分函数应用:函数本体 + 已经写死的实参,剩下的位置由 ? 让出
$f = str_replace('a', 'b', ?);

use 捕获的是外部作用域里的变量,闭包体里还要再写一遍调用;PFA 是把这行代码里已经写死的实参直接固化进调用位置,外面不需要多一个变量名,也不需要多一层 use (...)。

省掉的东西

典型的一段:前缀剥离。

// before
$prefix = 'user_';
$strip = function (string $key) use ($prefix): string {
return str_replace($prefix, '', $key);
};

// 8.6
$strip = str_replace('user_', '', ?);

数组映射、字符串规整这类一行回调尤其明显——闭包体只剩一个函数调用的时候,fn($x) => f($x) 基本可以被 f(?) 替掉,读起来只剩被调用的那个函数名。

可读性上的取舍

str_replace('a', 'b', ?) 这种参数少、位置一目了然的情况,比箭头函数更直接。

参数一多就不一定了。占位符是按位置生效的,人眼得先数清楚 ? 落在第几个参数上,才知道生成的闭包要几个实参、顺序是什么。参数签名长、或者 ? 夹在中间的时候,一个正常的 fn 反而更快读懂。

另外需要类型声明、默认值、多步逻辑的场景,PFA 都表达不了,老老实实写闭包。它是一个替掉最薄那层包装的工具,不是替代闭包。

常见误用

以为 ? 会自动补全参数。 它只是让出这个位置,不是「可选参数」。生成的闭包照样要求调用方把空位补齐。

想跳过中间参数只固定后面的。 位置是硬约束。要固定第三个参数,前两个位置就得用 ? 占着,调用方按顺序传进来——这种时候不如直接写闭包。

把位置写错。 str_replace(?, 'b', $s) 生成的是「只差第一个参数」的闭包,跟 str_replace('a', 'b', ?) 完全不是一回事。语法上不报错,跑起来才发现参数对不上。

在循环里反复构造。 这个和下面那条优化直接相关。

同批的闭包优化:只落了缓存这一半

这一版的闭包相关 RFC 原本是两块:

  1. 对从不接触 $this 的闭包自动推断为 static;
  2. 把完全无状态的闭包缓存起来,PHP 不再每次执行到那一行就分配一个新的闭包对象。

8.6 只落了第二块。自动推断 static 那一半被放弃了——实现没法可靠地识别出全部边界情况,推断错方向会直接把 $this 的语义改掉,代价比收益大。所以依赖「闭包自动变 static」的写法在这一版里依然不成立,该手写 static fn 的还得手写。

json_decode() 现在会报出错位置

解析失败时会指出失败发生在字符串中的哪个位置。调试拼接出来的一长串 JSON 时,不用再靠肉眼从某个偏移量开始数。

8.6 里一起落地的其他东西

  • Io\Poll 轮询 API
  • Time\Duration
  • readonly 属性默认值
  • clamp()
  • SortDirection 枚举
  • 更安全的 session 默认值
  • 类常量上的 #[\Override]

参考

  • 发布时间表:
  • PHP 官网:
复制全文 生成海报 PHP PHP8.6 闭包 函数式

推荐文章

程序员茄子在线接单