## 不向后兼容的变更

### PHP 核心

#### `"array"` 和 `"callable"` 别名

在 class_alias() 中，不再允许使用 `"array"` 和 `"callable"` 作为类的别名名称

#### 宽松比较不可比较的对象

之前，对不可比较的对象（例如枚举、CurlHandle 和其他内部类）进行宽松布尔比较时存在不一致性。如果与布尔字面量 `$object == true` 进行比较，则其行为与 `(bool)$object` 相同；如果与静态未知值 `$object == $true` 进行比较，则始终返回 `false`。此行为现已统一，始终遵循 `(bool)$object` 的行为。

#### gc_collect_cycles 的返回值

gc_collect_cycles() 的返回值不再包括通过循环间接收集的字符串和资源。

#### 在 final 子类中替换 static 关键字

现在允许在 final 子类中将 static 替换为 self 或具体类名。

#### tick 处理程序

tick 处理程序现在会在所有关闭函数和析构方法执行完毕、输出处理程序清理完成后停用。

#### Trait 绑定

Trait 现在会在父类之前绑定。这是一个细微的行为变更，但更符合用户的预期。

#### 编译和类链接过程中的错误

编译和类链接过程中产生的错误现在一律延迟处理，并在编译或类链接完成后统一处理。若在编译或类链接期间产生致命错误，将立即处理所有已延迟的错误，且不调用用户定义的错误处理程序。

#### 用户定义的错误处理程序抛出的异常

用户定义的错误处理程序在处理类链接错误时抛出的异常，不再升级为致命错误，也不会阻止链接过程。

#### 应用的注解在编译期间出错

将 `#[\Attribute]` 应用于抽象类、枚举、接口或 Trait 时，会在编译期间触发错误。此前，该注解虽可添加，但在调用 ReflectionAttribute::newInstance() 时才会抛出错误。通过使用新的 `#[\DelayedTargetValidation]` 注解，可将此错误从编译期延迟至运行时。

#### disable_classes INI 配置项

已移除 disable_classes INI 配置项，因其会导致引擎的多项假设失效。

#### 解构非数组值

使用 `[]` 或 list() 解构非数组值（`null` 除外）时，现在会发出警告。

#### 与类型转换相关的警告

当浮点数（或看起来像浮点数的字符串）无法精确表示为整数时，将其转换为整型会发出警告。此行为适用于显式和隐式的整型转换。

将 NAN 转换为其他类型时，现在会发出警告。

### Bzip2

当 `$block_size` 不在 1 到 9 之间时，bzcompress() 现在会抛出 ValueError。

当 `$work_factor` 不在 0 到 250 之间时，bzcompress() 现在会抛出 ValueError。

### DOM

现在克隆 DOMNamedNodeMap、DOMNodeList、Dom\NamedNodeMap、Dom\NodeList、Dom\HTMLCollection 和 Dom\DtdNamedNodeMap 会失败。此前此类操作从未生成有效的对象，因此预计不会产生实际影响。

### FileInfo

当 `$filename` 包含 nul 字节时，finfo_file() 和 finfo::file() 现在抛出 ValueError 而非 TypeError，以使抛出的错误类型与语言其他部分保持一致。

### Intl

该扩展现在要求最低 ICU 57.1。

IntlDateFormatter::setTimeZone()/datefmt_set_timezone() 在类未初始化或克隆失败时，现在会抛出 IntlException。

所有 Locale 方法在 locale 参数包含 null 字节时，现在均抛出 ValueError。

`Collator::SORT_REGULAR`在处理数字字符串时的行为现已与 ext/standard 中的 `SORT_REGULAR` 保持一致。

### LDAP

ldap_get_option() 和 ldap_set_option() 当传递无效选项时现在抛出 ValueError。

### MBString

Unicode 数据表已更新至 Unicode 17.0

### MySQLi

对已构造的对象再次调用 mysqli 构造方法现已不可行，并会抛出 Error。

### ODBC

ODBC 现在假定至少支持 ODBC 3.5 的功能，已移除用于控制相关 ODBCVER 定义及构建系统 flag。

ODBC 不再提供针对特定驱动（DB2 除外）的构建 flag，并移除了针对这些驱动的特殊处理。在非 Windows 系统上，强烈建议使用 iODBC 或 unixODBC 等驱动管理程序。

### Opcache

Opcache 扩展现已始终内置于 PHP 二进制文件中，并始终加载。INI 配置项 opcache.enable 和 opcache.enable_cli 仍会生效。

已移除 --enable-opcache/--disable-opcache 配置选项，构建过程不再生成 opcache.so 或 php_opcache.dll 文件。

使用 `zend_extension=opcache.so` 或 `zend_extension=php_opcache.dll` 的 INI 配置项会触发警告。

### PCNTL

pcntl_exec() 在 `$args` 参数的元素包含 null 字节时会抛出 ValueError。

pcntl_exec() 在 `$env_vars` 参数的元素或 key 包含 null 字节时会抛出 ValueError。

### PCRE

该扩展在编译时未启用半废弃的 PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK 编译选项。

### PDO

与 `PDO::FETCH_CLASS` 结合使用的构造方法参数现在遵循标准的 CUFA（call_user_func_array()）语义。这意味着字符串 key 将作为命名参数。此外，不再自动包装按值参数，传递给引用参数，而是会发出常规的 `E_WARNING` 警告。若需将变量以引用方式传入构造方法参数，应使用通用的数组值引用赋值方式：`$ctor_args = [&$valByRef]`。

在调用 PDO::fetch()、PDO::fetchObject() 或 PDO::fetchAll() 期间尝试调用 PDOStatement::setFetchMode()，例如通过将语句对象作为构造方法参数传入以实现对象映射等技巧，现在会抛出 Error。

常量 `PDO::FETCH_GROUP`、`PDO::FETCH_UNIQUE`、`PDO::FETCH_CLASSTYPE`、`PDO::FETCH_PROPS_LATE` 和 `PDO::FETCH_SERIALIZE` 的值已发生变化。

若 `PDO::FETCH_PROPS_LATE` 与非 `PDO::FETCH_CLASS` 的获取模式一同使用，现在会抛出 ValueError，与其他获取 flag 的行为保持一致。

若在 PDO::fetchAll() 中将 `PDO::FETCH_INTO` 用作获取模式，现在会抛出 ValueError，与 `PDO::FETCH_LAZY` 的行为类似。

### PDO_FIREBIRD

当尝试为 Firebird 驱动返回的 PDOStatement 设置过长的游标名称时，现在会抛出 ValueError。

### PDO_SQLITE

SQLite 的 PDO::quote() 在字符串包含 null 字节时，会根据错误模式抛出异常或发出警告。

PDO::sqliteCreateCollation() 在 callback 返回类型不正确时会抛出异常，使其行为更符合 Pdo\Sqlite::createCollation()。

### POSIX

posix_kill() 在 process_id 参数超出平台支持范围（有符号整数或长整型范围）时会抛出 ValueError；posix_setpgid() 在 process_id 或 process_group_id 小于零或超出平台支持范围时也会抛出 ValueError。

posix_setrlimit() 在 hard_limit 或 soft_limit 参数小于 -1，或 soft_limit 大于 hard_limit 时会抛出 ValueError。

### Reflection

ReflectionAttribute::newInstance() 现在可能在内部注解应用到无效目标时抛出错误，前提是该错误通过 #[\DelayedTargetValidation] 注解从编译时延迟到了运行时。

### Session

向会话写入数据时，若 $_SESSION 中的 key 包含竖线字符（`|`），现在会发出警告，而非静默失败。

session_start() 对 options 参数的校验更为严格：若该数组不是关联数组，会抛出 ValueError；若 read_and_close 的值类型与 int 不兼容，则抛出 TypeError。

将整数 `0` 作为 `locales` 参数传递给 setlocale() 不再受支持，现会抛出 TypeError。

### SimpleXML

向 SimpleXMLElement::xpath() 传入返回结果非节点集的 XPath 表达式时，现在会发出警告并返回 `false`，而非静默失败并返回空数组。

### SNMP

snmpget()、snmpset()、snmp2_get()、snmp2_set()、snmp3_get()、snmp3_set() 和 SNMP::__construct() 在主机名过长或包含 null 字节、端口号为负数或大于 65535、超时或重试次数小于 -1 或过大时，会抛出 ValueError。

### SOAP

SoapClient::__doRequest() 现在接受新的可选参数 `$uriParserClass`，该参数可接收 string 或 `null`。传入 `null` 表示使用原有的基于 parse_url() 的方法，而传入 Uri\Rfc3986\Uri 或 Uri\WhatWg\Url 时则会使用新的后端解析器。

### Sockets

socket_create_listen()、socket_bind() 和 socket_sendto() 在端口号小于 0 或大于 65535，或提示数组中的任一项使用数字索引时，会抛出 ValueError。

socket_addrinfo_lookup() 在提示值无法转换为整数时会抛出 TypeError，若这些值发生溢出，则可能抛出 ValueError。

使用 `MCAST_LEAVE_GROUP`/`MCAST_LEAVE_SOURCE_GROUP` 选项调用 socket_set_option() 时，若传入的值不是有效的对象或数组，会抛出异常。

在多播上下文中调用 socket_set_option() 时，若创建的套接字不属于 `AF_INET`/`AF_INET6` 协议族，会抛出 ValueError。

### SPL

ArrayObject 不再接受枚举，因为修改 $name 或 $value 属性可能破坏引擎设想。

SplFileObject::fwrite() 的参数 `$length` 现在允许为 null，默认值由 `0` 改为 `null`。

### 标准

此前，使用 printf 系列函数时，若格式化字符串中的格式符未指定精度，会错误地将精度重置，而非将其视为精度为 0。

### Tidy

tidy::__construct()、tidy::parseFile() 和 tidy::parseString() 在配置中包含无效值或尝试设置只读内部条目时会抛出 ValueError；若配置 key 不是 string，则抛出 TypeError。

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