PHP 8.4.1 Released!

其它变更

核心变化

FFI

opcache.preload_user 是当前系统用户时,现在允许在预加载期间使用 FFI::load()。以前,如果设置了 opcache.preload_user 指令,则预加载期间无法调用 FFI::load()

FPM

如果 socket 路径比操作系统支持的路径长度更长,则 FPM CLI 测试现在会失败。

Opcache

在 CLI 和 phpdbg SAPI 中,以 root 身份运行时,不再需要设置 opcache.preload_user 指令来进行预加载。在其它 SAPI 中,以 root 身份运行时需要此指令,因为在 SAPI 切换到非特权用户之前进行预加载。

Streams

如果在 socket 连接上有任何缓冲数据,而不是等待更多数据,fread() 阻塞会立即返回。

内存流在偏移量超过末尾时不会失败。而是在下次写入时内存会增加,并且旧末尾和偏移量之间的数据将使用零字节填充,类似于文件的工作方式。

现在,stat() 访问操作(像 file_exists() 及其类似这样)将使用真实路径而不是实际的 stream 路径。这与 stream 的打开方式保持一致。

SAPI 模块的变更

CLI

STDOUTSTDERRSTDIN 流不再因资源销毁而关闭,这主要是在 CLI 完成时关闭。然而,仍然可以使用 fclose() 和类似函数明确关闭这些流。

函数变更

核心

gc_status() 添加下列 8 个字段:

  • "running" => bool
  • "protected" => bool
  • "full" => bool
  • "buffer_size" => int
  • "application_time" => float:总的应用时间,以秒为单位(包含 collector_time)
  • "collector_time" => float:垃圾回收所花费的时间,单位为秒(包括 destructor_time 和 free_time)
  • "destructor_time" => float:在垃圾回收期间执行析构方法的时间,单位为秒
  • "free_time" => float:在垃圾回收期间花费在释放值上的时间,单位为秒

class_alias() 现在支持创建内部类的别名。

在运行时使用 ini_set('open_basedir', ...); 设置 open_basedir 时,不再接受包含父目录(..)的路径。以前只禁止以 .. 开头的路径。这可以通过在路径前加上./ 来轻松规避。

用户异常处理程序现在可以在关闭期间捕获异常。

highlight_string()highlight_file() 的 HTML 结果已经改变。外部 HTML 标签之间的空格已移除。换行符和空格不再转换为 HTML 实体。整个 HTML 现在包装在 <pre> 标签中。外部的 <span> 标签已经与 <code> 标签合并。

Calendar

easter_date() 现在在 64 位系统上支持 1970 到 20 亿年,以前它只支持 1970 到 2037 年。

Curl

curl_getinfo() 现在支持两个新常量:CURLINFO_CAPATHCURLINFO_CAINFO。如果 option 为 null,则会显示以下两个额外的键:"capath""cainfo"

DOM

DOMCharacterData::appendData() 的返回值临时修改为 true

DOMDocument::loadHTML()DOMDocument::loadHTMLFile()、 和 DOMDocument::loadXML() 现在有了临时返回类型 bool。之前,返回类型是 DOMDocument|bool,但是自 PHP 8.0.0 起,DOMDocument 不再是静态可调用,所以不能返回。

Gd

imagerotate() 的签名已经更改。已经移除 $ignore_transparent 参数,因为自 PHP 5.5.0 起已忽略。

Intl

datefmt_set_timezone()(及其别名 IntlDateformatter::setTimeZone())现在在成功时返回 true,以前返回 null

IntlBreakiterator::setText() 现在在失败时返回 false,之前返回 null。现在在成功时返回 true,以前返回 null

IntlChar::enumCharNames() 现在返回 bool。之前成功时返回 null,失败时返回 false

当设置了无效的区域,IntlDateFormatter::__construct() 将抛出 U_ILLEGAL_ARGUMENT_ERROR

MBString

mb_strtolower()mb_convert_case() 实现了对希腊字母 sigma 的条件转换规则,条件转换只适用于 MB_CASE_LOWERMB_CASE_TITLE 模式,不适用于 MB_CASE_LOWER_SIMPLEMB_CASE_TITLE_SIMPLE

mb_decode_mimeheader() 根据 RFC 2047 的要求解释 QPrint 编码的 MIME 编码单词中的下划线,它们将转换为空格。在这样的 MIME 编码单词中,下划线必须被编码为 "=5F"

在极少数情况下,mb_encode_mimeheader() 会对输入字符串进行传输编码,在 PHP 8.2 中会将输入字符串作为原始 ASCII 传递。

当输入字符串使用 QPrint 编码时,mb_encode_mimeheader() 不再丢弃 NUL(零)字节。之前会导致某些文本编码的字符串,特别是 UTF-16 和 UTF-32,会被 mb_encode_mimeheader 破坏。

mb_detect_encoding() 现在的的“非严格”模式行为如文档中所述。之前,如果在所有候选编码中输入字符串的相同字节(比如,第一个字节)是无效的,将会返回 false。一般来说,当看到无效字节时,将会从考虑(consideration)中剔除候选编码,如果相同的输入字节剔除了考虑中的所有剩余编码,将返回 false。另一方面,如果所有的候选编码一个个都剔除了,它将返回最后剔除的那个,而不考虑字符串中可能遇到的编码错误。这与文档中描述的行为不同,文档中说:“如果 strict 设置为 false,将返回最接近的匹配编码”。

mysqli

$constructor_args 参数不为空且类没有构造方法时,mysqli_fetch_object() 现在抛出 ValueError 而不是 Exception

当都没有传递 $read$error 参数时,mysqli_poll() 现在会抛出 ValueError

mysqli_field_seek()mysqli_result::field_seek() 现在返回类型指定为 true 而不是 bool

ODBC

odbc_autocommit() 现在接受 $enable 参数为 null。传递 null 与只传递 1 个参数的行为相同,即表明是否启用自动提交功能。

PGSQL

$constructor_args 参数不为空且类没有构造方法时,pg_fetch_object() 现在抛出 ValueError 而不是 Exception

当指定的表无效时,pg_insert() 现在抛出 ValueError 而不是 E_WARNING

当字段的值/类型与 PostgreSQL 的类型不匹配时,pg_insert()pg_convert() 会抛出 ValueErrorTypeError,而不是 E_WARNING

pg_fetch_result()pg_field_prtlen()pg_field_is_null()$row 参数现在可以为 null。

Random

mt_srand()srand() 变更为不使用检查参数的数量的方式来确定是否应该使用随机种子。传递 null 将生成随机种子,0 将使用 0 作为种子。函数现在与 Random\Engine\Mt19937::__construct() 一致。

Reflection

ReflectionClass::getStaticProperties() 的返回类型不再可为 null。

标准

unserialize() 所触发的 E_NOTICE 被提升为 E_WARNING

如果输入包含未使用的字节,unserialize() 现在会抛出新的 E_WARNING

array_pad() 现在只接受数组元素可拥有的最大数量限制,以前每次最多只能添加 1048576 个元素。

strtok() 在开始标切分时,如果没有提供 token,则引发 E_WARNING

当生成 salt 失败时,password_hash() 现在将底层的 Random\RandomException 链到 ValueError$previous Exception

如果使用数组作为 proc_open()$command,则现在必须至少有一个非空元素。否则会抛出 ValueError

如果 $command 数组是无效命令,proc_open() 将返回 false,而不是随后产生警告的资源对象。 Windows 系统已经是这种行为,但如果使用 posix_spawn 实现(大多数 Linux、BSD 和 MacOS 平台),也会是这种行为。 在一些旧平台上,由于不支持 posix_spawn,因此这种行为不会改变。

array_sum()array_product() 现在会在数组中的值不能转换为 int/float 时发出警告。之前会忽略数组和对象,而其他所有值都被强制转换为 int。此外,定义了数字转换的对象(例如 GMP)现在会强制转换,而不是忽略。

现在 number_format()$decimals 可以正确处理负整数。$decimals 为负数时,$num 值会四舍五入到小数点前 $decimals 位,而之前的 $decimals 会忽略负数,并且四舍五入到小数点后 0 位。

strrchr() 中增加了新的参数 $before_needle,它的行为与 strstr()stristr() 函数中的对应参数类似。

对于未包含关闭引号的最后一个字段,str_getcsv()fgetcsv() 现在返回空字符串,而不是带单个 null 字节的字符串。

其它扩展变更

核心

在类型 bool 的值上使用 自增/减运算符(++/--)将会抛出警告。这是因为虽然目前没有效果,但是将来行为将是 $bool += 1

在类型 null 的值上使用 自减运算符(--)将会抛出警告。这是因为虽然目前没有效果,但是将来行为将是 $null -= 1

内部对象实现 _IS_NUMBER 转换,但不是重写加减法的 do_operator 处理程序,现在可以像 $o += 1$o -= 1 一样递增和递减。

DOM

DOM 的生命周期机制已经被重写,这样默默删除的节点仍然可以获取,之前这样做会导致异常。

SQLite3

SQLite3 类现在抛出 SQLite3Exception(继承 Exception)而不是 Exception

SQLite 错误代码现在在 exception error code 中传递,而不是包含在错误消息中。

INI 文件处理更变

  • 已弃用 assert.* INI 设置。这包括以下 INI 设置:

    如果设置的值等于默认值,则不会发出弃用通知。应该使用 zend.assertions INI 设置。

  • zend.max_allowed_stack_size 是新的 INI 指令,用于设置允许的最大栈大小。可能的值是 0(检测进程或线程的最大栈大小)、-1(无限制)或正数的单位为字节的值。默认值为 0。当无法检测到进程或线程的最大的栈大小时,使用已知的系统默认值。设置的值过高效果等同于不限制栈的大小。Fiber 使用 fiber.stack_size 作为允许的最大栈大小。当进程调用栈超过 zend.max_allowed_stack_size-zend.reserved_stack_size 个字节时,将抛出 Error,以防止栈溢出引发分段错误,目的是使调试更容易。在没有控制递归调用内部函数或者魔术方法 __toString()__clone()__sleep()__destruct() 期间,栈的大小会增加。这与栈缓冲区溢出无关,也不是安全特性。

  • zend.reserved_stack_size 是新的 INI 指令,用于设置预留的栈大小(以字节为单位)。当检查栈大小时,会从最大允许的栈大小中减去,作为缓冲区。

性能

DOM

现在遍历 DOMNodeList 时使用了缓存,因此默认情况下请求元素不再需要花费两次的时间。

从节点获取文本内容现在避免了分配,从而提高了性能。

DOMChildNode::remove() 现在运行性能是 O(1)。

标准

file() flag 错误检查现在快了大约 7%。

SPL

RecursiveDirectoryIterator 现在循环目录时执行更少的 I/O。

添加备注

用户贡献的备注

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