紧接 8.1→8.2、8.2→8.3、8.3→8.4,本文聚焦 PHP 8.4 → 8.5 的升级。8.5 发布于 2025 年 11 月 20 日,标题是"Smarter, Faster, Built for Tomorrow"——这是 PHP 8.x 系列的最后一个大版本。PHP 官方已经公布 8.5 之后将进入 PHP 9 开发周期,8.6 预计 2026 年底发布,8.x 系列将在 2027 年 11 月完全 EOL。
8.5 有三个值得关注的新特性:管道操作符 |>(期待多年的特性终于落地)、URI 扩展(原生 URL 解析)、clone with(一行克隆并修改属性)。前两个是真正会改变代码写法的特性,第三个是 DDD Value Object 场景下的完美语法糖。另外还有 #[\NoDiscard] Attribute 和 cURL 持久化共享句柄两个"运维安全"类改进。
一、核心差异速查表
| 维度 | PHP 8.4 | PHP 8.5 | 影响程度 |
|---|---|---|---|
| 管道操作符 | ❌ 靠函数嵌套或 array_reduce 实现 | ✅ |> 原生,从左到右传递 |
语法层重磅 |
| URI 扩展 | ❌ 需用 parse_url + 手动拼接 | ✅ 原生 Uri\Uri 对象,RFC 3986/WHATWG 标准 |
代码层 |
| clone with | ❌ 需写 with 方法 | ✅ clone $obj with (x: newVal, y: 'val') |
可选改进 |
| #[\NoDiscard] | ❌ 无 | ✅ 标记函数返回值不可丢弃,遗漏时告警 | 安全/质量 |
| cURL 持久化句柄 | ❌ 每次 curl_init 都是新连接 | ✅ CurlShareHandle 跨请求共享连接池 |
性能 |
| 支持状态(2026-10) | ✅ Bugfix 到 2025-08 | ✅ 刚发布,Bugfix 到 2026-11 | 推荐升级 |
二、8.5 三大新特性详解
1. 管道操作符 |> —— PHP 开发者期待了整整十年
管道操作符在 Elixir、F#、Rust、TypeScript 等语言里都有,PHP 社区从 2016 年就开始讨论,2025 年终于正式进入 8.5。它的作用是把"函数嵌套"改成"从左到右顺读":
// PHP 8.4 及以前:函数嵌套,读起来反人类
$result = json_encode(
array_map(fn($user) => ['name' => ucfirst($user['name']), 'email' => $user['email']],
array_filter($users, fn($u) => $u['status'] === 'active')
),
JSON_PRETTY_PRINT
);
// PHP 8.5:管道操作符,从左到右顺读
$result = $users
|> array_filter(fn($u) => $u['status'] === 'active')
|> array_map(fn($user) => ['name' => ucfirst($user['name']), 'email' => $user['email']])
|> json_encode(..., JSON_PRETTY_PRINT);
// 更简洁的写法
$result = $users
|> array_filter(..., ...)
|> array_map(fn($u) => ['name' => ucfirst($u['name']), 'email' => $u['email']], ...)
|> json_encode(..., JSON_PRETTY_PRINT);
管道操作符的规则很简单:$value |> callable 等价于 callable($value)——上一步的输出自动作为下一步 callable 的第一个参数。如果你的 callable 第一个参数就是要处理的值,直接套就行;如果不是,用占位符或者闭包调整:
// 直接套:strlen 的第一个参数就是值
$len = 'hello' |> strlen; // 5
// 不是第一个参数的情况:用闭包或 8.5 引入的 partial application
$result = 'a/b/c' |> str_replace('/', '-', ...);
// 这里 str_replace('/','-',$value),管道注入 $value 为第三个参数
// 也可以这样写(更明确)
$result = 'a/b/c' |> str_replace(...); // ❌ 不对,管道注入的是第一个参数
// 要用命名参数或闭包
$result = 'a/b/c' |> fn($s) => str_replace('/', '-', $s); // ✅
// 或者用 partial application
$result = 'a/b/c' |> str_replace('/', '-', ...);
管道操作符还能配合类方法调用:
$report = $db->query('SELECT * FROM orders')
|> ResultSet::from(...)
|> ->groupBy('customer_id')
|> ->total('amount')
|> ->formatAsCurrency()
|> report_make(..., ...);
管道操作符不是"必须用"——它是一个让代码更易读的工具。喜欢函数式风格的人会大量用;习惯 OOP 的人可以按需用在数据转换链路上。
2. URI 扩展 —— PHP 终于有原生 URL 解析了
在 8.5 之前,PHP 开发者要处理 URL,只能靠 parse_url()(简单够用但粗糙)或者自己实现 RFC 3986 兼容的解析器(复杂易错)。8.5 终于加了一个原生的 Uri 扩展,提供完整的 URI 对象模型:
// PHP 8.5 原生 URI
use Uri\Uri;
$uri = Uri::from('https://api.example.com:8443/v2/users?id=123#profile');
echo $uri->scheme; // "https"
echo $uri->host; // "api.example.com"
echo $uri->port; // 8443
echo $uri->path; // "/v2/users"
echo $uri->query; // "id=123"
echo $uri->fragment; // "profile"
echo $uri->userinfo; // ""
// 可以修改并生成新 URI(不可变)
$newUri = $uri->withPath('/v3/users')->withQueryString(['id' => '456', 'sort' => 'desc']);
// WHATWG URL 标准兼容(对 web 开发重要)
$whatwg = Uri::from('http://example.com/ foo bar ');
// WHATWG 模式下空格自动转成 %20,这和浏览器 JS 的 URL 解析一致
URI 扩展的底层用的是 liburiparser(RFC 3986/3987 标准实现),也支持 WHATWG URL API 模式。对 PHP 开发者来说,这意味着终于不用自己写或依赖第三方包来做 URL 拼接/规范化/解析了。
3. clone with —— DDD Value Object 的完美语法糖
结合 readonly class,clone with 让"不可变对象修改属性返回新对象"这种 DDD 常见模式变得极简:
// PHP 8.4:手写 with 方法
readonly class Money {
public function __construct(
public float $amount,
public string $currency,
) {}
public function withAmount(float $newAmount): self {
return new self($newAmount, $this->currency); // ← 每次都要写这个
}
}
// PHP 8.5:clone with 语法
readonly class Money {
public function __construct(
public float $amount,
public string $currency,
) {}
// 不需要写 with 方法了!
}
$money = new Money(100, 'CNY');
$newMoney = clone $money with (amount: 200);
// $money 还是 100 元(不可变)
// $newMoney 是 200 元的新实例
clone with 可以一次改多个属性:clone $user with (name: 'Alice', email: 'a@b.com')。和 readonly class + Property Hooks 配合,就是完整的 DDD Value Type 语言级支持。
三、其他值得关注的改进
#[\NoDiscard] Attribute —— 安全网一样的 Attribute
#[NoDiscard]
function generateToken(): string {
return bin2hex(random_bytes(32));
}
// 调用方忘记用返回值:
generateToken(); // ⚠️ Deprecated 警告:Discarded return value of function generateToken()
// 这个 Attribute 专门标记那些返回值"必须被使用"的函数
// 比如 generateToken 返回的 token 不用就丢了(严重 bug)
// 或者 throw_if 这种返回值有语义的 helper 函数
cURL 持久化共享句柄
// PHP 8.4:每次 curl_init 都建立新连接
$ch1 = curl_init('https://api.example.com/a');
$ch2 = curl_init('https://api.example.com/b');
// → 两次完整的 SSL/TLS 握手
// PHP 8.5:共享句柄,连接池复用
$share = curl_share_init();
curl_share_setopt($share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
curl_share_setopt($share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
$ch1 = curl_init('https://api.example.com/a');
curl_setopt($ch1, CURLOPT_SHARE, $share);
$ch2 = curl_init('https://api.example.com/b');
curl_setopt($ch2, CURLOPT_SHARE, $share);
// → 第二次请求直接复用 SSL session + 连接池,延迟减半
curl_close($ch1); curl_close($ch2);
curl_share_close($share);
在批量请求或高频 API 调用场景下,持久化句柄可以把 SSL 握手开销减半。但注意多线程/多进程场景下要加锁,否则会有竞态。
四、破坏性变更清单
8.4→8.5 的破坏性变更同样不多(PHP 官方对 minor 版本升级的定性就是"大部分项目应该可以不做修改就能运行")。主要集中在:
- 某些
hash_*系列函数在 8.5 移除了对已经不再安全的算法的支持(如salsa20) date_create_from_format在某些 edge case 下行为调整libxml扩展默认启用 stricter 的错误报告
建议还是跑一次 Rector php85 规则集,自动扫一遍 Deprecated。
五、升级实操指南
路径 A:Composer 项目
# composer.json:
# "php": "^8.5.0"
# "config": { "platform": { "php": "8.5.x" } }
# Rector 扫 Deprecated
composer require rector/rector --dev
vendor/bin/rector process src --set php85
# update
composer update --with-all-dependencies
# 注意:8.5 刚发布,部分包可能还没声明支持 ^8.5
# 如果遇到 composer constraint 冲突,用 composer update --ignore-platform-reqs 先装起来测
# 然后在 issue 里催包作者更新
路径 B:Windows 官方包
# PHP 8.5 官方包已在 2025-11-20 发布
# https://windows.php.net/download/
# 选 VS16 x64 NTS 或 TS
# 流程不变:
# 备份旧 php 目录 → 解压新包 → php.ini 同步配置 → 迁移 extension → 改 PATH → php -v 验证
# 注意 8.5 的 extension 版本和 8.4 不同,旧的 .dll 可能不兼容,需要下载 8.5 对应版本
路径 C:源码编译
wget https://www.php.net/distributions/php-8.5.1.tar.xz
tar xvf php-8.5.1.tar.xz && cd php-8.5.1
# 8.5 新增了 liburiparser 依赖(URI 扩展)
sudo apt-get install -y liburiparser-dev libxml2-dev libssl-dev libcurl4-openssl-dev \
libzip-dev libicu-dev libonig-dev libjpeg-dev libpng-dev libfreetype6-dev \
libxslt1-dev libwebp-dev libgmp-dev
./configure \
--prefix=/usr/local/php85 \
--enable-fpm \
--enable-opcache \
--enable-jit \
--with-jit=ir \
--enable-mysqlnd \
--enable-mbstring \
--with-curl --with-zip --with-intl --with-openssl \
--with-jpeg --with-freetype --with-webp \
--with-bz2 --with-readline --with-gmp \
--enable-bcmath \
--enable-uri # ← 8.5 新增!启用 URI 扩展
make -j$(nproc) && sudo make install
六、PHP 8.x 系列总结
到此为止,PHP 8.0→8.5 六个版本的升级指南全部完成。这里做一张对照表,方便你规划自己的升级路线:
| 版本 | 发布 | 重磅特性 | 破坏性变更数量 | 生态状态(2026-10) |
|---|---|---|---|---|
| 8.0 | 2020-11 | 属性提升/union/nullsafe/match/JIT | ★★★★★ | ❌ 完全 EOL |
| 8.1 | 2021-11 | 枚举/readonly/Fiber | ★ | ❌ 完全 EOL |
| 8.2 | 2022-12 | readonly class/first-class callable/动态属性 Error | ★★★ | ❌ 完全 EOL |
| 8.3 | 2023-11 | 类型化常量/Override/Trait 可见性 | ★ | ⚠️ 仅剩安全修复 |
| 8.4 | 2024-11 | Property Hooks/非对称可见性/IR JIT | ★★ | ⚠️ 刚进安全修复期 |
| 8.5 | 2025-11 | 管道操作符/URI 扩展/clone with | ★ | ✅ Bugfix 支持中 |
推荐升级路线(2026 年版):
- 当前还在 7.4/8.0/8.1:先升到 8.2(解决动态属性 Error),再直接升 8.5
- 当前在 8.2/8.3:直接跳到 8.5(8.4 的 Property Hooks 值得单独看,但可以跳过)
- 当前在 8.4:升到 8.5,拿到管道操作符 + URI 扩展
PHP 8.x 系列还有大概一年半的安全支持窗口(到 2027 中后),之后就进入 PHP 9 时代。但对于大多数项目来说,8.5 已经是一个稳定、现代、功能完整的版本,可以长期跑下去。
参考链接
- PHP 8.5 Release Notes(中文):https://www.php.net/releases/8.5/zh.php
- PHP 8.5 Migration Guide:https://www.php.net/manual/en/migration85.php
- PHP 版本支持时间表:https://www.php.net/supported-versions.php