PHP 8.4.1 Released!

不向后兼容的变更

PHP 核心中不向后兼容的变更

以数组形式访问非数组

尝试以数组方式访问 nullboolintfloatresource (例如 $null["key"])将会抛出 notice 通知。

get_declared_classes() 函数

get_declared_classes() 函数将不再返回匿名的类,假如它们没有被实例化的话。

fn 关键词

fn 成为了保留关键词。需要特别注意,它不能再做为函数名或类名使用,但是仍然可以做为方法名和常量名存在。

文件尾部的 <?php 标签

文件尾部的 <?php 标签(不包含空行)将会被解释成 PHP 起始标记。之前,不是解释为短开始标记,后跟文字 php 并导致语法错误(short_open_tag=1),就是解释为文字 <?php 字符串(short_open_tag=0)。

Stream 封装协议

在 stream 上使用 include/require 时,将使用 STREAM_OPTION_READ_BUFFER 选项调用 streamWrapper::stream_set_option()。编写的自定义 stream 封装协议可能需要实现 streamWrapper::stream_set_option() 方法以避免警告(始终返回 false 就足够了)。

Serialization 序列化

序列化类型 o 被移除。因为它不是由 PHP 生成的,这可能会影响到之前项目中手动生成的序列化字符串。

密码算法常量

密码哈希算法标识符现在是可空字符串,而不再是整数。

应用中如果正常使用了常量 PASSWORD_DEFAULT,PASSWORD_BCRYPT,PASSWORD_ARGON2I 和 PASSWORD_ARGON2ID 将不会受到影响。

htmlentities() 函数

htmlentities() 如果与仅支持基本实体替换(basic entity substitution)的编码一起使用,现在将发出 notice(而不是严格标准的 warning),在这种情况下,相当于 htmlspecialchars()

fread() and fwrite() 函数

fread()fwrite() 在操作失败的时候会返回 false。之前的版本中会返回空字符串或 0。EAGAIN/EWOULDBLOCK 不视为故障。

这些函数现在也会在失败时发出 NOTICE 通知,例如当试图写入一个只读文件资源时。

BCMath 任意精度数学

如果传递了例如 "32foo" 这种格式不正确的数字,BCMath 函数现在将发出警告。和以前一样,参数将解释为 0。

CURL

现在尝试序列化 CURLFile 类将会生成异常。之前仅会在反序列化时引发。

弃用 CURLPIPE_HTTP1,并在 cURL 7.62.0 起不再支持。

弃用 curl_version()$version 参数。如果传递了任何不等于默认 CURLVERSION_NOW 的值,则会引发警告并忽略参数。

日期和时间

DateTimeDateTimeImmutable 实例上调用 var_dump() 或类似方法将不会忘记对象上的可访问属性。

DateInterval 对象的比较(使用 ==< 等)现在将生成警告并始终返回 false。之前所有的 DateInterval 对象都认为相等,除非它们有属性。

Intl

idn_to_ascii()idn_to_utf8() 的默认参数的值现在为 INTL_IDNA_VARIANT_UTS46,而不是已弃用的 INTL_IDNA_VARIANT_2003

MySQLi

内嵌服务器功能已移除。自 PHP 7.0 起就已破坏了。

未记录的 mysqli::$stat 属性已移除,以支持 mysqli::stat()。

OpenSSL

openssl_random_pseudo_bytes() 函数现在将在错误情况下抛出异常,类似于 random_bytes()。特别是,如果请求的字节数小于或等于零,则会引发 Error;如果无法收集到足够的随机性,则会引发 Exception。如果函数不抛出异常,则 $crypto_strong 输出参数保证始终为 true,因此不需要手动检查它。

正则表达式(Perl 兼容)

当使用 PREG_UNMATCHED_AS_NULL 模式时,后跟不匹配的捕获组现在也将设置为 null(如果启用了偏移捕获,则为 [null, -1])。这意味着 $matches 的大小将始终相同。

PHP 数据对象

尝试序列化 PDOPDOStatement 实例现在将生成 Exception 而不是 PDOException,这与其它不支持序列化的内部类一致。

反射

现在如果尝试对 Reflection 对象序列化将会生成异常。从未支持反射对象序列化并会引起反射对象错误。现在已明确禁止。

ReflectionClassConstantReflectionMethodReflectionProperty 类常量的值发生了变化。

PHP 标准库(SPL)

现在对 ArrayObject 实例调用 get_object_vars() 将始终返回 ArrayObject 本身(或子类)的属性。之前,除非指定了 ArrayObject::STD_PROP_LIST flag,否则将返回包装后的 array/object。

其它受到影响的操作有:

(array) 转换不受影响。它们将继续返回包装数组或 ArrayObject 属性,具体取决于是否使用 ArrayObject::STD_PROP_LIST flag。

如果传递零,SplPriorityQueue::setExtractFlags() 将引发异常。以前,这会在执行下个提取操作时生成可恢复的致命错误。

除了 Serializable 接口之外,ArrayObjectArrayIteratorSplDoublyLinkedListSplObjectStorage 现在还支持 __serialize()__unserialize() 机制。这意味着在旧版本上创建的序列化负荷仍然可以反序列化,但旧版本将无法理解 PHP 7.4 创建的新负荷(payloads)。

Tokenizer

token_get_all() 现在将为非法字符发出 T_BAD_CHARACTER token,而不是在 token stream 中留下漏洞。

接收到的 Cookies

从 PHP 7.4.11 开始,为了安全考虑,接受到的 Cookie 中的 names 参数不再被 URL 编码。

添加备注

用户贡献的备注 1 note

up
20
happydog at kennel17
3 years ago
Re: "The o serialization format has been removed. As it is never produced by PHP, this may only break unserialization of manually crafted strings."

This little-o serialisation format was used by PHP3 but was never generated by PH PHP4 or above. The deserialization code still recognised it, though, for reasons of backwards-compatibility with PHP3.

However, based on a bit of investigation, it looks like this code has been broken for about 15 years, so although this is listed as a deprecation, in practice it wasn't.

See this Stack Overflow question for a really great answer, with a lot more detail about this: https://stackoverflow.com/questions/65289729/what-was-phps-o-serialization-format-for
To Top