## 其他变更

### 核心变更

#### 闭包

闭包名称已调整为包含父函数的名称和定义所在的行号，以便于区分，例如在堆栈跟踪中。

#### Fiber

现在允许在析构函数执行期间进行 Fiber 切换。此前由于与垃圾回收冲突而被阻止。

析构函数现在可以在单独的 Fiber 中执行：

当在 Fiber 中触发垃圾回收时，GC 调用的析构函数将在单独的 Fiber 中执行：即 gc_destructor_fiber。如果该 Fiber 挂起，将创建一个新的 Fiber 来执行剩余的析构函数。之前的 gc_destructor_fiber 不再被 GC 引用，如果没有在其他地方被引用，则可能被回收。析构函数被挂起的对象在析构函数返回或 Fiber 被回收之前不会被回收。

#### 输出处理器

传递给 ob_start() 的 `flags` 参数的输出处理器状态标志现在会被清除。

output_add_rewrite_var() 现在使用 `url_rewriter.hosts` 代替 `session.trans_sid_hosts` 来选择将要被重写的主机。

### SAPI 模块变更

#### apache2handler

已移除对已停止支持的 Apache 2.0 和 2.2 的支持。最低要求的 Apache 版本现在是 2.4。

#### CLI

内置服务器在指定文件无法找到时，会通过遍历父目录递归查找索引文件。此前，如果路径看起来像是指向一个文件（即最后一个路径部分包含句点），则会跳过此过程，并返回 404 错误。现在的行为已变更为在所有情况下都查找索引文件。

#### FPM

刷新不带正文的头信息现在将成功。

状态页面新增了一个字段来显示内存峰值。

用于 Solaris/Illumos 的 /dev/poll `events.mechanism` 设置已被废弃。

### 变更的函数

#### 核心

trigger_error() 和 user_error() 的返回类型现在是 true 而不是 bool。

#### DOM

DOMDocument::registerNodeClass() 现在的暂定返回类型为 true 而不是 bool。 实际上它只可能返回 `true`。

#### Hash

hash_update() 现在的暂定返回类型为 true 而不是 bool。 实际上它只可能返回 `true`。

#### Intl

`NumberFormatter::ROUND_TOWARD_ZERO` 和 `NumberFormatter::ROUND_AWAY_FROM_ZERO` 已作为 `NumberFormatter::ROUND_DOWN` 和 `NumberFormatter::ROUND_UP` 的别名添加，以与新的 `PHP_ROUND_*` 模式保持一致。

ResourceBundle::get() 现在的暂定返回类型为 `ResourceBundle|array|string|int|null`。

idn_to_ascii() 和 idn_to_utf8() 函数在 `domain` 名称为空或过长时，现在始终抛出 ValueError。

idn_to_ascii() 和 idn_to_utf8() 函数在 `variant` 参数不是 `INTL_IDNA_VARIANT_UTS46` 时，现在始终抛出 ValueError。

#### LibXML

libxml_set_streams_context() 现在在将非流上下文资源传递给函数时立即抛出 TypeError，而不是在使用流上下文时才抛出。

#### MBString

mb_strcut() 在处理无效的 UTF-8 和 UTF-16 字符串时的行为现在更加一致。对于有效的 UTF-8 和 UTF-16 字符串没有行为变化。

#### ODBC

odbc_fetch_object()、odbc_fetch_array() 和 odbc_fetch_into() 的 `row` 参数现在的默认值为 `null`，与 odbc_fetch_row() 保持一致。此前默认值分别为 `-1`、`-1` 和 `0`。

#### OpenSSL

openssl_csr_new() 中的 `extra_attributes` 现在设置 CSR 属性而非主题 DN，修正了之前的错误行为。

openssl_csr_new() 中的 `dn` 现在允许为单个条目设置 array 类型的值。

openssl_csr_sign() 新增了 `serial_hex` 参数，允许以十六进制格式设置序列号。

在 OpenSSL 3.2 以下版本中，使用 openssl_x509_parse() 解析省略秒数的 ASN.1 UTCTime 时会失败（相关字段返回 `-1`）。OpenSSL 3.3 及以上版本已无法加载此类证书。

#### PDO

现在可以通过 PDO::getAttribute() 获取 `PDO::ATTR_STRINGIFY_FETCHES` 属性的值。

新增了 `PDO::PGSQL_ATTR_RESULT_MEMORY_SIZE` 常量，用于通过 PDO::getAttribute() 获取支持该功能的驱动程序的查询结果内存使用量。

#### PDO_FIREBIRD

现在可以通过 PDO::getAttribute() 获取 `FB_ATTR_DATE_FORMAT`、`FB_ATTR_TIME_FORMAT`、`FB_ATTR_TIMESTAMP_FORMAT` 属性的值。

新增了用于指定事务隔离级别和访问模式的属性。与此功能相关的五个常量已被添加：

- `Pdo\Firebird::TRANSACTION_ISOLATION_LEVEL`
- `Pdo\Firebird::READ_COMMITTED`
- `Pdo\Firebird::REPEATABLE_READ`
- `Pdo\Firebird::SERIALIZABLE`
- `Pdo\Firebird::WRITABLE_TRANSACTION`

使用持久连接时，构造函数中现在会进行活跃性检查。

构建的内容会根据 ibase.h 中 `FB_API_VER` 的值而变化。可以使用新的静态方法 Pdo\Firebird::getApiVersion() 来获取此信息。此信息现在也在 phpinfo() 中显示。

五种新数据类型现已可用： `INT128`, `DEC16`, `DEC34`, `TIMESTAMP_TZ`, `TIME_TZ` 。 这些类型从 Firebird 4.0 开始可用。

#### PDO_MYSQL

现在可以通过 PDO::getAttribute() 获取 `PDO::ATTR_FETCH_TABLE_NAMES` 属性的值。

#### PDO_PGSQL

支持通过 `PDO::PGSQL_ATTR_RESULT_MEMORY_SIZE` 获取查询的内存使用量。

如果列的类型为 `FLOAT4OID` 或 `FLOAT8OID`，其值现在将作为 float 而不是 string 返回。

#### PGSQL

pg_select() 的 `conditions` 参数现在是可选的，并接受空数组。

#### Phar

Phar::setAlias(), Phar::setDefaultStub() 方法现在的暂定返回类型为 true 而不是 bool。

#### POSIX

posix_isatty() 现在在文件描述符/流参数无效时会设置错误号。

#### Reflection

ReflectionGenerator::getFunction() 现在可以在生成器执行完毕后调用。

#### Sockets

socket_create_listen() 的 `backlog` 参数的默认值现在为 `SOMAXCONN`。此前为 `128`。

#### Sodium

sodium_crypto_aead_aes256gcm_* 函数现在可在具有 ARM 加密扩展的 aarch64 CPU 上使用。

#### SPL

SplPriorityQueue::insert(), SplPriorityQueue::recoverFromCorruption(), SplHeap::insert(), SplHeap::recoverFromCorruption() 方法现在的暂定返回类型为 true 而不是 bool。

SplObjectStorage 现在实现了 SeekableIterator。

#### Standard

password_hash() 中 `PASSWORD_BCRYPT` 散列算法的默认 `'cost'` 值已从 `10` 增加到 `12`。

debug_zval_dump() 现在会指示数组是否为紧凑（packed）数组。

long2ip() 的返回类型现在为 string， 而不是 `string|false`。

highlight_string() 的返回类型现在为 string|true，而不是 `string|bool`。

print_r() 的返回类型现在为 string|true，而不是 `string|bool`。

##### 使用 round() 进行四舍五入

round() 函数的 `mode` 参数已扩展为 `RoundingMode|int`， 接受新的 RoundingMode 枚举实例。

round() 函数新增了四种模式： RoundingMode::PositiveInfinity, RoundingMode::NegativeInfinity, RoundingMode::TowardsZero, RoundingMode::AwayFromZero

整数舍入的内部实现已被重写，使其更易于验证正确性和维护。作为重写的结果，一些舍入错误已被修复。例如，此前将 `0.49999999999999994` 舍入到最近的整数会得到 `1.0`，而不是正确的结果 `0.0`。其他输入也可能受到影响，与早期 PHP 版本相比可能产生不同的输出。

修复了 round() 函数的"预舍入"导致的错误。此前，使用"预舍入"将诸如 `0.285`（实际为 `0.28499999999999998`）的值视为十进制数并舍入为 `0.29`。然而，"预舍入"会错误地舍入某些数字，因此此修复移除了"预舍入"并更改了数字的比较方式，使值能作为十进制数正确舍入。

round() 能够处理的最大精度已扩展了一位数字。例如，`round(4503599627370495.5)` 此前返回 `4503599627370495.5`，现在返回 `4503599627370496`。

### 对扩展的其他变更

#### cURL

要求的最低 libcurl 版本现在为 7.61.0。

`CURLOPT_DNS_USE_GLOBAL_CACHE` 选项不再有任何效果，会被静默忽略。该底层功能在 libcurl 7.11.1 中被弃用，在 libcurl 7.62.0 中被移除。

#### GMP

现在可以将 GMP 对象转换为 bool，而不是发出 `E_RECOVERABLE_ERROR`。转换行为已重载，使得表示值 `0` 的 GMP 对象被转换为 `false`。

#### LibXML

要求的最低 libxml2 版本现在为 2.9.4。

#### Intl

Intl 类的行为已规范化，在尝试使用未初始化的对象或克隆失败时，始终抛出 Error 异常。

#### MBString

Unicode 数据表已更新至 Unicode 16.0。

#### MySQLnd

支持来自 MySQL 9 的新 VECTOR 数据类型。

#### OpenSSL

要求的最低 OpenSSL 版本现在为 1.1.1。

#### PDO_PGSQL

要求的最低 libpq 版本现在为 10.0。

#### PGSQL

要求的最低 libpq 版本现在为 10.0。

#### SPL

SplFixedArray 中的越界访问现在抛出 OutOfBoundsException 类型的异常，而不是 RuntimeException。由于 OutOfBoundsException 是 RuntimeException 的子类，在尝试捕获这些异常时不会产生行为变化。

#### XSL

类型化属性 XSLTProcessor::$cloneDocument 和 XSLTProcessor::$doXInclude 现在已声明。

#### Zlib

要求的最低 zlib 版本现在为 1.2.11。

### 性能

#### 核心

改进了在高并发负载下 ZTS 构建中浮点数解析和格式化的性能。这影响了 printf() 系列函数以及序列化函数，如 json_encode() 或 serialize()。

仅使用 `%s` 和 `%d` 格式说明符的 sprintf() 将被编译为等效的字符串插值，避免了函数调用和重复解析格式字符串的开销。

#### BCMath

改进了数字转换和运算的性能。

#### DOM

DOMNode::C14N() 在不使用 xpath 查询的情况下性能大幅提升。对于有数万个节点的文档，时间性能可以轻松提升两个数量级。

改进了 XML 序列化的性能并减少了内存消耗。

减少了节点类的内存使用。

#### FTP

改进了 FTP 上传的性能，大文件上传速度最高可提升 10 倍。

#### Hash

新增了 SHA-256 的 SSE2 和 SHA-NI 实现。在支持的 CPU 上性能提升约 1.3 倍（SSE2）和 3 至 5 倍（SHA-NI）。感谢 Colin Percival / Tarsnap 提供了此优化。

#### MBString

mb_strcut() 在处理 UTF-8 和 UTF-16 字符串时速度大幅提升。

查找 mbstring 编码名称的速度大幅提升。

SJIS-win 到 Unicode 的转换性能大幅提升。

#### MySQLnd

改进了 MySQLnd 转义的性能。

#### PCRE

改进了命名捕获组的性能。

#### Random

改进了 Random\Randomizer 的性能，特别针对 Random\Randomizer::getBytes() 和 Random\Randomizer::getBytesFromString() 方法。

#### SimpleXML

改进了 XML 序列化的性能并减少了内存消耗。

#### Standard

strspn() 和 strcspn() 的性能大幅提升。它们现在以线性时间运行，而不是受二次时间限制。

改进了 strpbrk() 的性能。

get_browser() 的速度大幅提升，在某些测试用例中最高可提升 1.5 至 2.5 倍。

`↑` and `↓` to navigate • `Enter` to select • `Esc` to close • `/` to open