不向后兼容的变更

尽管本节没有明确说明,但每个新函数类、interface、枚举常量都可能导致抛出重复声明 Error

PHP 核心

exit() 行为变更

exit()(和 die())语言结构现在的行为更像函数。这意味着现在可以传递 callable,受 strict_types 声明语句的影响,并且现在执行往常的类型强制,而不是将任何非整数值转换为字符串。

因此,将无效类型传递给 exit()die() 现在会导致抛出 TypeError

比较过程中的递归

比较期间遇到递归现在会导致 Error 异常,而不是 E_ERROR 致命错误。

间接修改 readonly 属性

不再允许在 __clone() 里间接修改 readonly 属性,例如 $ref = &$this->readonly。这在 readonly 初始化中已禁止,并且是“克隆期间 readlony 重新初始化”实现中的一个疏忽。

常量的类型变更

PHP_DEBUGPHP_ZTS 常量现在为 bool 类型。以前为 int 类型。

Temporary 文件名长度

上传文件和 tempnam() 函数创建的文件名现在为 13 个字节。总长度仍取决于平台。

移除 E_STRICT 错误级别

已移除 E_STRICT 错误级别,因为其在 PHP 引擎中不再使用。已弃用 E_STRICT 常量。

扩展类常量现已类型化

以下扩展类常量现在在其常量上声明类型:

迁移资源到对象

多个 resource 已迁移到 object。除非另有说明,否则 is_resource() 的返回值检查应替换为 false 检查。

DBA

DBA 函数现在接受并返回 Dba\Connection 对象,而不是 dba_connection resource

ODBC

ODBC 函数现在接受并返回 Odbc\Result 对象,而不是 odbc_result resource

ODBC 函数现在接受并返回 Odbc\Connection 对象,而不是 odbc_connection resource

SOAP

SoapClient::$httpurl 属性现在是 Soap\Url 对象,而不是 soap_url resource。 检查使用 is_resource()(即 is_resource($client->httpurl))应该替换为检查 是否为 null(即 $client->httpurl !== null)。

SoapClient::$sdl 属性现在是 Soap\Sdl 对象,而不是 soap_sdl resource。 检查使用 is_resource()(即 is_resource($client->sdl))应该替换为检查 是否为 null(即 $client->sdl !== null)。

新的警告和异常

添加了因编程错误(即将无效值提供给参数)而触发新的警告和异常。

Curl

如果 timeout 参数小于 0 或大于 PHP_INT_MAXcurl_multi_select() 现在会抛出 ValueError

Gd

当传入无效的 quality 时,imagejpeg(), imagewebp(), imagepng(), imageavif() 现在抛出 ValueError

当传递无效的 speed 参数值时,imageavif() 现在将抛出 ValueError

如果 widthheight 参数溢出,imagescale() 现在将抛出 ValueError

当传入无效的 mode 参数时,imagescale() 现在将抛出 ValueError

如果 subplus 参数溢出,imagefilter() 现在使用 IMG_FILTER_SCATTER 过滤器将抛出 ValueError

Gettext

如果 domain 是空字符串,bind_textdomain_codeset(), textdomain(), d()*gettext() 现在 抛出 ValueError

Intl

resourcebundle_get()ResourceBundle::get() 和在 ResourceBundle 对象上访问偏移量现在会抛出:

如果 locale 无效,则 IntlDateFormatter::__construct() 抛出 ValueError

如果 locale 无效,则 NumberFormatter::__construct() 抛出 ValueError

MBString

mb_encode_numericentity()mb_decode_numericentity() 现在检测 map 是否仅由 int 构成,如果不是,则抛出 ValueError

如果 type 无效,mb_http_input() 现在始终抛出 ValueError

mb_http_output() 现在检测 encoding 是不是不包含 null 字节,如果包含,会抛出 ValueError

ODBC

row 小于或等于 0 时,odbc_fetch_row() 返回 false。在这种情况下会发出 warning。

PCNTL

pcntl_sigprocmask()pcntl_sigwaitinfo()pcntl_sigtimedwait() 函数现在会抛出:

如果 mode 不是 SIG_BLOCKSIG_UNBLOCKSIG_SETMASK 中的一个,pcntl_sigprocmask() 现在将抛出 ValueError

pcntl_sigtimedwait() 函数现在将抛出:

  • 如果 seconds 小于 0 则抛出 ValueError
  • 如果 nanoseconds 小于 0 或者大于 1e9,则抛出 ValueError
  • 如果 secondsnanoseconds0,则抛出 ValueError

SimpleXML

使用非 XML 对象调用 simplexml_import_dom() 将抛出 TypeError 而不是 ValueError

标准

round() 函数现在会验证 mode 的值,如果无效,则抛出 ValueError。之前无效模式会解释为 PHP_ROUND_HALF_UP

separatorenclosure 参数值的长度不为一个字节,或者 escape 参数值不为一个字节或者空字符串,str_getcsv() 现在将抛出 ValueError。该行为已与 fputcsv()fgetcsv() 行为相同。

如果 mode 无效,php_uname() 函数现在会抛出 ValueError

unserialize()"allowed_classes" 选项如果不是类名 array,现在会抛出 TypeErrorValueError

XMLReader

传递无效的字符编码给 XMLReader::open()XMLReader::XML() 现在会引发 ValueError

传递包含 null 字节的 string,之前会发出 warning,现在会引发 ValueError

XMLWriter

传递包含 null 字节的 string,之前会发出 warning,现在会引发 ValueError

XSL

XSLTProcessor::setParameter() 现在会在参数包含 null 字节时抛出 ValueError。这实际上从一开始就没有正确运行过,这就是它现在抛出异常的原因。

现在,使用非 XML 对象调用 XSLTProcessor::importStyleSheet() 会引发 TypeError 而不是 ValueError

如果在求值期间调用 PHP 函数回调失败,则现在会抛出而不是发出 warning。

DOM

如果无法分配新节点,某些 DOM 方法以前会返回 false 或带有 code DOM_PHP_ERRDOMException。现在,它们会一致地抛出带有 code DOM_INVALID_STATE_ERRDOMException。这种情况极少发生,受影响的可能性也很低。因此,DOMImplementation::createDocument() 现在暂定返回类型为 DOMDocument,而不是 DOMDocument|false

以前,可以克隆 DOMXPath 对象,但会导致对象不可用。现在则不可以,克隆 DOMXPath 对象会引发 Error

已移除 DOMImplementation::getFeature() 方法。

GMP

GMP 类现在是 final,并且再也不能继承。

MBString

对于无效字符串(包含编码错误),mb_substr() 现在以与大多数其他 mbstring 函数相同的方式解释字符索引。这意味着 mb_strpos() 返回的字符索引可以传递给 mb_substr()

对于 SJIS-Mac (MacJapanese) 字符串,传递给 mb_substr() 的字符索引现在指向的是将字符串转换为 Unicode 时生成的 Unicode 码点的索引。这很重要,因为大约 40 个 SJIS-Mac 字符在转换为 Unicode 时会变成多个 Unicode 代码点的序列。

MySQLi

已移除未使用和未记录的常量 MYSQLI_SET_CHARSET_DIR

已移除 MYSQLI_STMT_ATTR_PREFETCH_ROWS 常量。mysqlnd 无法使用该功能。

已移除 MYSQLI_CURSOR_TYPE_FOR_UPDATEMYSQLI_CURSOR_TYPE_SCROLLABLE 常量。此功能从未实现过,无论是 mysqlnd 还是 libmysql。

已移除未使用的 MYSQLI_TYPE_INTERVAL 常量(当前是 MYSQLI_TYPE_ENUM 的存根(stub)和别名)。

MySQLnd

对于 MySQL 服务器 8.0.24 及以上版本,MySQL 服务器等待超时报告的错误 code 已从 2006 更改为 4031

Opcache

64 位架构上 opcache.interned_strings_buffer 设置的最大值现在是 32767。以前是 4095

JIT

JIT 的默认配置值分别从 opcache.jit=tracingopcache.jit_buffer_size=0 更改为 opcache.jit=disableopcache.jit_buffer_size=64M

这不会影响默认的可观察行为,因为默认情况下 JIT 仍处于禁用状态。但是,现在是通过 opcache.jit 设置而不是 opcache.jit_buffer_size 禁用。这可能会影响之前仅通过 opcache.jit_buffer_size 启用 JIT 的用户,而无需使用 opcache.jit 指定 JIT 模式。要启用 JIT 编译,请相应地设置 opcache.jit 配置值。

如果启用了 JIT 编译,当 JIT 编译器的初始化因任何原因而失败时,PHP 将在启动时退出并出现致命错误。

PCNTL

pcntl_sigprocmask()pcntl_sigwaitinfo()pcntl_sigtimedwait() 函数现在在失败时始终返回 false。以前在某些情况下,它可能返回值 -1

PCRE

捆绑的 pcre2lib 已更新至版本 10.44。因此,这意味着 {,3} 现在识别为量词而不是文本。此外,UCP 模式下某些字符类的含义已发生改变。请参阅 » PCRE2 变更日志,了解完整的变更日志。

PDO_DBLIB

Pdo\Dblib::ATTR_STRINGIFY_UNIQUEIDENTIFIERPdo\Dblib::ATTR_DATETIME_CONVERT 属性现在是 bool 属性,而不是 int 属性。因此,通过 PDO::setAttribute() 设置属性并通过 PDO::getAttribute() 检索属性并返回 bool 值。

PDO_FIREBIRD

PDO::ATTR_AUTOCOMMIT 属性现在是 bool 属性,而不是 int 属性。因此,通过 PDO::setAttribute() 设置属性并通过 PDO::getAttribute() 检索属性并返回 bool 值。

该扩展现在公开了一些 Firebird C++ API,因此编译此扩展现在需要 C++ 编译器。此外,现在必须针对 fbclient 3.0 或更高版本编译该扩展。

PDO_MYSQL

PDO::ATTR_AUTOCOMMITPDO::ATTR_EMULATE_PREPARESPDO::MYSQL_ATTR_DIRECT_QUERY 属性现在是 bool 属性,而不是 int 属性。因此,通过 PDO::setAttribute() 设置属性并通过 PDO::getAttribute() 检索属性并返回 bool 值。

PDO_PGSQL

DSN 的凭证在设置时优先于 PDO 构造方法中的凭证,更接近文档状态。

SimpleXML

SimpleXMLElement 不仅是 XML 元素的表示,而且还是 RecursiveIterator。在 PHP 8.4.0 之前,它的某些方法(例如 SimpleXMLElement::asXML()SimpleXMLElement::getName())以及将此类实例转换 string 会隐式重置迭代器。

这可能会导致意外的无限循环,因为已倒回迭代器。例如:

<?php

$xmlString
= "<root><a><b>1</b><b>2</b><b>3</b></a></root>";
$xml = simplexml_load_string($xmlString);

$nodes = $xml->a->b;
foreach (
$nodes as $nodeData) {
echo
"nodeData: " . $nodeData . "\n";

$xml = $nodes->asXml();
}

会导致无限循环。

nodeData: 1
nodeData: 2
nodeData: 2
nodeData: 2
nodeData: 2
nodeData: 2
nodeData: 2
// ...

但是,此行为现已得到纠正,除非明确倒回,否则 SimpleXMLElement 将不再隐式重置迭代器数据。这意味着前面的示例现在将导致:

nodeData: 1
nodeData: 2
nodeData: 3

SOAP

SoapClient::$typemap 现在是 array,而不是 resource。使用 is_resource() 检查(即 is_resource($client->typemap))应替换为对 null 的检查(即 $client->typemap !== null)。

SOAP 扩展获得了对 session 扩展的可选依赖。如果在编译 PHP 时未使用 session 扩展,并且启用了 --enable-rtld-now 配置 flag,则如果还使用了 SOAP 扩展,则将发生启动错误。要解决此问题,请不要使用 rtld-now 或加载 session 扩展。

标准

当使用 strcspn() 并将 characters 设为空字符串时,现在将返回字符串的长度,而不是错误地停止在第一个 null 字节处。

http_build_query() 现在可以正确处理支持的枚举。

stream_bucket_make_writeable()stream_bucket_new() 现在将返回 StreamBucket 实例而不是 stdClass 实例。

Tidy

构造方法失败现在会引发 exception,而不是发出 warning 并导致对象损坏。

XML

xml_set_()*_handler() 函数现在声明并检查 handler 参数的 callable|string|null 有效签名。此外,现在检查与使用 xml_set_object() 设置的对象方法名称相对应的 string 类型的值,以查看该方法是否存在于先前传递的对象的类中。这意味着现在必须始终在将方法名称设置为 callable 之前调用 xml_set_object()。传递空字符串来禁用处理程序仍然是允许的,但已弃用。

然而,由于 xml_set_object() 和传递非 callable 的字符串已弃用。建议使用直接引用该方法的 callable 来更改此类实例。

添加备注

用户贡献的备注

此页面尚无用户贡献的备注。
To Top