34、PHP 8.4 方法或功能修改 - MBString:Unicode 字符数据库已更新到版本 16
在 PHP 8.4 中,MBString(Multibyte String)扩展引入了一项重要更新:Unicode 字符数据库已更新至版本 16。这意味着,MBString 现在支持最新的 Unicode 字符集和规范,确保了对更广泛的字符集、符号和表情符号(emoji)的支持。
Unicode 15.0、15.1 和 16.0 分别增加了 4,489、627 和 5,185 个新字符。此外,这三个 Unicode 版本的更新还支持了 11 种新的书写系统。然而,对于 MBString 扩展来说,重要的更新是在字符大小写折叠规则方面,这影响到像 mb_strtolower
、mb_strtoupper
这样的函数,以及东亚宽度值的分配,用于确定给定字符是被视为标准宽度还是宽字符(mb_strwidth
)。
通过对 Unicode 16 的支持,MBString 扩展能够处理所有最新的 Emoji 字符,并且具备最为更新的大小写折叠和字符宽度信息。
MBString 函数本身没有直接的变化。Unicode 字符数据是 MBString 扩展的一部分,将在所有 PHP 8.4 的函数中使用。
如何使用 MBString 处理 Unicode 字符
<?php
$str = "Hello, 👋🌍!";
echo mb_strlen($str, 'UTF-8'); // 正确处理表情符号
向后兼容性影响
UCD 16 当前是 Unicode 标准的最新版本,由于函数参数和返回值没有发生变化,因此不太可能引起任何向后兼容性问题。
然而,请注意,之前在旧版 PHP 中进行过大小写转换或宽度测量的数据,在 PHP 8.4 及以后的版本中可能会返回不同的数据。
以下是一些示例:
echo "Emoji: \u{1F6DC}, width: " . mb_strwidth("\u{1F6DC}");
// 输出: Emoji: 🛜, width: 2
WiFi 表情符号(🛜)是在 UCD 15 中添加的,旧版 PHP 无法识别 1F6DC 代码点,因此返回宽度为 1。
echo mb_strtoupper("\u{019b}") === "\u{a7dc}";
在 UCD 16 中,019b
字符(ƛ - 拉丁小写字母 Lambda 带横杠)有了新的大小写映射。PHP 8.3 及更早版本不支持这个大小写映射,因此 mb_strtoupper("\u{019b}")
会返回 "\u{019b}"
本身。而在 PHP 8.4 及以后版本中,mb_strtoupper("\u{019b}")
会返回 "\u{a7dc}"
。
上述代码片段使用了十六进制 Unicode 字符转义符,并放在双引号字符串中。
与其他功能的对比
Intl
扩展和 PCRE
扩展也在其操作中使用了 Unicode 字符数据库。
在 PHP 8.4 中,PCRE2
库更新到了 10.44,且 PCRE2
是基于 UCD 15 构建的。
Intl
扩展依赖于 ICU 库来提供 Unicode 数据表。在默认构建下,底层 ICU 库的 UCD 版本通常是 UCD 15。
尽管不太可能,但在 MBString、Intl 和 PCRE 扩展中处理字符时可能会出现边缘情况。例如,Unicode 16 中对 \u{019b}
字符的新大小写映射在 PCRE
扩展中没有被识别为大写字符:
preg_match('/\p{Ll}/u', "\u{019b}"); // Unicode 识别,匹配任何小写字符
// 在 PHP 8.3 和 8.4 中都能匹配
preg_match('/\p{Lu}/u', mb_strtoupper("\u{019b}")); // Unicode 识别,匹配任何大写字符
// 在 PHP 8.3 或 8.4 中都不会匹配,尽管它被认为是大写字符
请注意,UCD 版本号不匹配的问题在 PHP 8.4 中并不新鲜,UCD 不匹配导致问题的可能性是非常低的。