ConFoo 2025

不向后兼容的变更

尽管本节没有明确说明,但每个新函数类、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

Passing an invalid character encoding to XMLReader::open() or XMLReader::XML() now throws a ValueError.

Passing a string containing null bytes previously emitted a warning and now throws a ValueError.

XMLWriter

Passing a string containing null bytes previously emitted a warning and now throws a ValueError.

XSL

XSLTProcessor::setParameter() will now throw a ValueError when its arguments contain null bytes. This never actually worked correctly in the first place, which is why it throws an exception now.

Calling XSLTProcessor::importStyleSheet() with a non-XML object now throws a TypeError instead of a ValueError.

Failure to call a PHP function callback during evaluation now throws instead of emitting a warning.

DOM

Some DOM methods previously returned false or a DOMException with code DOM_PHP_ERR if a new node could not be allocated. They now consistently throw a DOMException with code DOM_INVALID_STATE_ERR. This situation is extremely unlikely and the probability of being affected is low. As a result DOMImplementation::createDocument() now has a tentative return type of DOMDocument instead of DOMDocument|false.

Previously, DOMXPath objects could be cloned, but resulted in an unusable object. This is no longer possible, and cloning a DOMXPath object now throws an Error.

The DOMImplementation::getFeature() method has been removed.

GMP

The GMP class is now final and cannot be extended anymore.

MBString

On invalid strings (those with encoding errors), mb_substr() now interprets character indices in the same manner as most other mbstring functions. This means that character indices returned by mb_strpos() can be passed to mb_substr().

For SJIS-Mac (MacJapanese) strings, character indices passed to mb_substr() now refer to the indices of the Unicode codepoints which are produced when the string is converted to Unicode. This is significant because around 40 SJIS-Mac characters convert to a sequence of multiple Unicode codepoints.

MySQLi

The unused and undocumented constant MYSQLI_SET_CHARSET_DIR has been removed.

The MYSQLI_STMT_ATTR_PREFETCH_ROWS constant has been removed. The feature is unavailable with mysqlnd.

The MYSQLI_CURSOR_TYPE_FOR_UPDATE and MYSQLI_CURSOR_TYPE_SCROLLABLE constants have been removed. This functionality was never implemented, neither with mysqlnd nor with libmysql.

The unused MYSQLI_TYPE_INTERVAL constant, which is currently a stub and an alias for MYSQLI_TYPE_ENUM, has been removed.

MySQLnd

The error code reported for MySQL server wait timeouts has been changed from 2006 to 4031 for MySQL server versions 8.0.24 and above.

Opcache

The maximum value of the opcache.interned_strings_buffer setting on 64bit architectures is now 32767. Previously it was 4095.

JIT

The default configuration values for the JIT changed from opcache.jit=tracing and opcache.jit_buffer_size=0 to opcache.jit=disable and opcache.jit_buffer_size=64M, respectively.

This does not affect the default observable behavior, as the JIT is still disabled by default. However, it is now disabled through the opcache.jit setting, rather than opcache.jit_buffer_size. This may affect users who previously enabled JIT through opcache.jit_buffer_size exclusively, without also specifying a JIT mode using opcache.jit. To enable JIT compilation, set the opcache.jit config value accordingly.

If JIT compilation is enabled, PHP will now exit with a fatal error on startup if the initialization of the JIT compiler failed for any reason.

PCNTL

The pcntl_sigprocmask(), pcntl_sigwaitinfo(), and pcntl_sigtimedwait() functions now always return false on failure. In some case previously it could return the value -1.

PCRE

The bundled pcre2lib has been updated to version 10.44. As a consequence, this means {,3} is now recognized as a quantifier instead of as text. Furthermore, the meaning of some character classes in UCP mode has changed. Consult the » PCRE2 Changelog for a full changelog.

PDO_DBLIB

The Pdo\Dblib::ATTR_STRINGIFY_UNIQUEIDENTIFIER and Pdo\Dblib::ATTR_DATETIME_CONVERT attributes now act as boolean attributes instead of integer attributes. Thus setting the attribute via PDO::setAttribute() and retrieving it via PDO::getAttribute() expects and or return a bool.

PDO_FIREBIRD

The PDO::ATTR_AUTOCOMMIT attribute now act as boolean attributes instead of integer attributes. Thus setting the attribute via PDO::setAttribute() and retrieving it via PDO::getAttribute() expects and or return a bool.

The extension now exposes some Firebird C++ APIs, therefore building this extension now requires a C++ compiler. Moreover, the extension must now be compiled against fbclient 3.0 or higher.

PDO_MYSQL

The PDO::ATTR_AUTOCOMMIT, PDO::ATTR_EMULATE_PREPARES, and PDO::MYSQL_ATTR_DIRECT_QUERY attributes now act as boolean attributes instead of integer attributes. Thus setting the attribute via PDO::setAttribute() and retrieving it via PDO::getAttribute() expects and or return a bool.

PDO_PGSQL

The DSN's credentials, when set, are given priority over their PDO constructor counterparts, being closer to the documentation states.

SimpleXML

SimpleXMLElement is not only a representation of an XML element, but it is also a RecursiveIterator. Prior to PHP 8.4.0, some of its methods (e.g. SimpleXMLElement::asXML() or SimpleXMLElement::getName()) and casting such instances to string would implicitly reset the iterator.

This could cause unexpected infinite loops as the iterator was rewound. For example:

<?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();
}

would result in an infinite loop.

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

However, this behavior has now been corrected, and a SimpleXMLElement will no longer implicitly reset the iterator data, unless explicitly rewound. Meaning the previous example would now result in:

nodeData: 1
nodeData: 2
nodeData: 3

SOAP

SoapClient::$typemap is now an array rather than a resource. Checks using is_resource() (i.e. is_resource($client->typemap)) should be replaced with checks for null (i.e. $client->typemap !== null).

The SOAP extension gained an optional dependency on the session extension. If PHP is built without the session extension and with the --enable-rtld-now configure flag enabled, startup errors will now occur if the SOAP extension is also used. To solve this either don't use rtld-now or load the session extension.

Standard

When using strcspn() with characters being the empty string, the length of the string is now returned instead of incorrectly stopping at the first null byte.

http_build_query() now correctly handles backed enums.

stream_bucket_make_writeable() and stream_bucket_new() will now return a StreamBucket instance instead of an instance of stdClass.

Tidy

Failures in the constructor now throw exceptions rather than emitting warnings and having a broken object.

XML

The xml_set_()*_handler() functions now declare and check for an effective signature of callable|string|null for the handler parameters. Moreover, values of type string that correspond to method names, of object set with xml_set_object() are now checked to see if the method exists on the class of the previously passed object. This means that xml_set_object() must now always be called prior to setting method names as callables. Passing an empty string to disable the handler is still allowed, but deprecated.

However, as xml_set_object() and passing non-callable strings is deprecated. It is recommended to change such instances with a callable referring to the method directly.

添加备注

用户贡献的备注

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