PHP 8.6 进入 Beta:PFA 通过、clamp() 与 Io\Poll 落地,readonly 属性可以写默认值了
PHP 8.6 正式版将于 2026 年 11 月 19 日发布。目前已进入 Beta 测试阶段,9 月 22 日执行功能冻结,两天后发布第一个 RC 候选版本。
来源:Laravel News(作者 Paul Redmond):
发布时间轴
- Alpha1–Alpha3:2026-07-02 ~ 07-30
- Beta1(软功能冻结):2026-08-13
- Beta3:2026-09-10
- 功能冻结:2026-09-22
- RC1:2026-09-24
- RC4:2026-11-05
- GA(正式发布):2026-11-19
该版本的产品负责人:Daniel Scherzer、Matteo Beccati、Joe Ferguson。
部分函数应用(Partial Function Application,PFA)
部分函数应用允许预先填充一部分函数参数,返回一个接收剩余参数的闭包。? 代表后续传入单个参数的占位符;... 代表剩余全部参数。
$makeSlug = str_replace(' ', '-', ?);
$makeSlug('Hello World'); // Hello-World
$titles = array_map(strtolower(?), $titles);
生成的闭包会完整保留原函数的参数名、类型声明与默认值。预先传入的参数在生成偏函数时求值,而不是调用闭包的时候才求值。配套的后续 RFC 规定:每一个 ? 占位符,在生成的闭包上都会成为必传参数,即便原函数的该参数是可选参数。该提案旧版本 2021 年被否决;第二版 RFC 以 33 票赞成、0 票反对获得通过。
clamp() 函数族
新增 clamp():如果传入值落在最小/最大区间内,则直接返回原值;超出边界则返回距离最近的边界值。
clamp(10, min: 0, max: 100); // 10
clamp(101, min: 0, max: 100); // 100
clamp(-1, min: 0, max: 100); // 0
支持所有可比较类型,包含字符串、DateTime 对象。如果传入的最小值大于最大值,会抛出 ValueError。该函数用来替代广为使用但容易写反的写法:min(max($value, $min), $max)。
Duration 时间时长类
PHP 8.6 新增 Time\Duration,这是一个 final readonly 类,用于表示秒表式时间长度,支持纳秒精度。提供各时间单位的工厂方法、算术运算方法,同时支持比较运算符。
use Time\Duration;
$oneSecond = Duration::fromSeconds(1);
$halfSecond = $oneSecond->divideBy(2);
$total = $oneSecond->add($halfSecond);
$delay = Duration::fromMilliseconds(100)->multiplyBy(2 ** $attempt);
$total > $delay; // 可直接使用比较运算符
也可以通过 ISO 8601 时长字符串构建实例。该类作为标准类型,供内核与新的轮询 API 接收使用,替代松散的整数、浮点数时间值。
只读属性支持默认值
PHP 8.6 起,readonly 属性可以设置默认值。8.6 版本之前,这么写属于编译错误;这让实现 PHP 8.4 只读接口属性时,写固定默认值非常别扭。
final readonly class CreateBooksTable implements Migration {
public string $name = '2026_01_01_create_books_table';
}
RFC 仅移除语法限制;readonly 语义不变,初始化之后依旧不能重新赋值。
函数参数直接书写文档注释
现在可以直接给参数写文档注释,ReflectionParameter::getDocComment() 可以读取该注释。不再需要在函数上方的 @param 标签重复写参数名称。
function search(
/** Terms to search for in the database */
string $query,
/** Maximum number of entries to return */
int $limit = 10,
): array {
// ...
}
静态分析工具与 IDE 可以直接读取参数上的注释。
Polling(轮询)API
全新命名空间 Io\Poll,为 PHP 提供统一封装的 IO 多路复用接口:Linux 下 epoll、BSD/macOS 下 kqueue、Solaris event ports、Windows WSAPoll。对于用户态实现事件循环、异步运行时的开发者,可以用来替代旧的 stream_select()。
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
}
}
}
RFC 说明该 API 首要目标服务 PHP 内部,例如信号处理、FPM 改进;其次供用户态异步框架使用。
SortDirection 枚举
内置全局枚举 SortDirection,包含 Ascending 升序、Descending 降序两个 case。目前 PHP 内核还没有函数直接接收该枚举;RFC 目的是提供统一标准类型,避免各个类库各自定义排序枚举,查询构建器是典型使用场景。
$query->orderBy('created_at', SortDirection::Descending);
枚举支持 __debugInfo() 魔术方法
PHP 8.1 刚引入枚举时,禁止枚举定义大部分魔术方法。PHP 8.6 放开限制,允许枚举实现 __debugInfo(),该魔术方法不依赖实例状态,用来自定义 var_dump() 输出内容。
enum Status: int {
case Ok = 200;
public function __debugInfo(): array {
return [__CLASS__ . '::' . $this->name . ' = ' . $this->value];
}
}
流(Stream)统一错误处理模型
流增加统一错误模型。新增 error_mode 上下文选项,可选:警告、抛出异常、静默;stream_last_errors() 返回结构化 StreamError 对象,获取上一次操作的错误。
$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;
}
}
StreamErrorCode 枚举定义超过 50 个语义化错误码。
URI 扩展增强(PHP 8.5 延续改进)
PHP 8.5 引入的 URI 扩展,新增 Builder 构建器类。无需创建大量中间对象,即可组装 URI。
$uri = new Uri\Rfc3986\UriBuilder()
->setScheme('https')
->setHost('example.com')
->setPath('/foo/bar')
->build();
配套 RFC 还新增了 getUriType()、getHostType() 方法,以及针对 URI 各组成部分的百分号编码函数。
Session 会话安全默认值变更
全新安装环境下,php.ini 三个 session 配置项更新默认值:
session.use_strict_mode:旧0→ 新1session.cookie_httponly:旧0→ 新1session.cookie_samesite:旧 未设置 → 新Lax
而 Laravel 框架自行接管 Session Cookie,绝大多数 Laravel 项目不受影响。直接使用 PHP 原生 Session 并且依赖旧默认配置的应用,请先阅读 Session defaults RFC。
参考
- 英文原文:
PHP 8.6 在发布前一定还会有变化:功能冻结日为 2026-09-22,GA 为 2026-11-19,在此之前各项 API 与默认值仍可能调整。