不向后兼容的变更

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

PHP 核心

exit() 行为变更

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

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

比较过程中的递归

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

间接修改 readonly 属性

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

常量的类型变更

PHP_DEBUG 和 PHP_ZTS 常量现在为 bool 类型。以前为 int 类型。

临时文件名长度

上传文件和 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_MAX,curl_multi_select() 现在会抛出 ValueError。

Gd

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

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

如果 width 或 height 参数溢出,imagescale() 现在将抛出 ValueError。

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

如果 sub 或 plus 参数溢出,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_BLOCK、SIG_UNBLOCK 或 SIG_SETMASK 中的一个,pcntl_sigprocmask() 现在将抛出 ValueError。

pcntl_sigtimedwait() 函数现在将抛出:

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

Session

设置一个非正值的 session.gc_divisor 或者一个负值的 session.gc_probability 现在会发出警告。

SimpleXML

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

标准

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

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

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

unserialize() 的 "allowed_classes" 选项如果不是类名 array,现在会抛出 TypeError 和 ValueError。

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。

Date

相对格式的 number 符号再次接受多个符号,例如 +-2。

DOM

如果无法分配新节点,某些 DOM 方法以前会返回 false 或带有 code DOM_PHP_ERR 的 DOMException。现在,它们会一致地抛出带有 code DOM_INVALID_STATE_ERR 的 DOMException。这种情况极少发生,受影响的可能性也很低。因此,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_UPDATE 和 MYSQLI_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=tracing 和 opcache.jit_buffer_size=0 更改为 opcache.jit=disable 和 opcache.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_UNIQUEIDENTIFIER 和 Pdo\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_AUTOCOMMIT、PDO::ATTR_EMULATE_PREPARES 和 PDO::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 来更改此类实例。

+添加备注

用户贡献的备注

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