PHP 8.6: 新增 grapheme_strrev 函数
Intl 扩展的 Grapheme 函数引入了一个新函数,叫做 grapheme_strrev,用于以字位单元作为反转字符串的顺序单位。
与 strrev 函数的区别在于,grapheme_strrev 是以“字素簇”(grapheme clusters)为单位进行操作的,而 strrev 则是以字节为单位对给定字符串进行反转。对于 ASCII 字符,strrev 和 grapheme_strrev 返回的结果完全一致;但对于包含多字节或多码点字符的字符串,grapheme_strrev 能够正常工作,因为它操作的单位是“字素”(grapheme,即书写系统中最小的功能单位)。
例如,以 Emoji 表情 👍🏽 为例:它是 Emoji 表情 👍 (U+1F44D) 与肤色修饰符 🏽 (U+1F3FD) 的组合。
strrev 函数会破坏这个 Emoji 的结构,因为它操作的是单个字节。
虽然目前没有名为 mb_strrev 的函数,但即使是支持多字节处理的反转函数,也会破坏这种结构,因为该 Emoji 是由两个多字节码点拼接而成的:A👍🏽C -> C 🏽👍A。
只有 grapheme_strrev 函数能正确地将字素簇作为一个整体单位进行反转,从而将 A👍🏽C 反转为 C👍🏽A,生成可读的文本。
新增的 grapheme_strrev 函数
/**
* Reverse a string by grapheme clusters.
* @param string $string The string to reverse
* @return string|false The reversed string, or false on failure
*/
function grapheme_strrev(string $string): string|false;该函数声明于全局命名空间中。
该字符串可能包含 NUL 字符,这些字符也将包含在反转后的字符串中。
使用示例
grapheme_strrev('ABCDE'); // EDCBA
grapheme_strrev('Apple🍏'); // 🍏elppA
grapheme_strrev('🇨🇳 - 🇳🇨'); // 🇳🇨 - 🇨🇳向后兼容性影响
grapheme_strrev 是一个在全局命名空间中声明的新函数。除非 PHP 应用在全局命名空间中声明了同名函数,否则此更改不会破坏现有的应用。
在 PHP 8.4 及更高版本中,可以在用户空间对该函数进行 Polyfill(兼容性填充):
function grapheme_strrev(string $string): string|false {
$units = grapheme_str_split($string);
if ($units === false) {
return false;
}
return implode('', array_reverse($units));
}上述 Polyfill 方案使用了 PHP 8.4 中新增的
grapheme_str_split函数。反过来,我们也可以利用正则表达式\X为grapheme_str_split函数本身提供 Polyfill。但这要求 PCRE 版本不低于 10.43;对于较旧的 PHP 版本而言,除非在编译时指定了自定义的 PCRE 版本,否则通常不会包含这一要求。