utf8_encode 和 utf8_decode 是命名错误的函数,它们很少是你想要的。
让我们看看你正在使用的编码:
htmlspecialchars($string, ENT_QUOTES, "UTF-8")
在这里,您告诉htmlspecialchars 您的字符串被编码为 UTF-8。到目前为止,一切顺利。
$string = utf8_decode(...);
现在,您告诉utf8_decode 将字符串从 UTF-8 转换为 ISO-8859-1 编码。 ISO-8859-1 是单字节编码,只能表示 256 个不同的字符,当然不包含任何表情符号。如手册所述:
字符串中不是有效 UTF-8 的字节,以及 ISO-8859-1 中不存在的 UTF-8 字符(即 U+00FF 以上的字符)被替换为 ?。
在执行完剩下的代码之后,你可以运行这个:
return utf8_encode(...)
这告诉utf8_encode 将您的 ISO-8859-1 字符串转换回 UTF-8。但是已经晚了,那些在ISO-8859-1中不存在的好看的emoji都已经变成了?s,再也没有办法找回来了。
如果你去掉 utf8_decode 和 utf8_encode 调用,你会遇到不同的问题:PCRE 正则表达式函数(例如 preg_replace)默认只对单个字节起作用,但在 UTF-8 中§ 是两个字节长。因此,当您替换字节 A7 时,您将替换“半个字符”,留下无效字符串。
您可以通过以下两种方式之一解决此问题:
- 将正则表达式保留为单字节模式,但匹配正确的字节序列,即
C2 A7;例如preg_replace('/\xC2\xA7([0-9a-f])/i', ...
- 通过添加the
u modifier 并引用§ 的Unicode 代码点A7 将正则表达式置于UTF8 模式;例如preg_replace('/\xA7([0-9a-f])/iu', ...
简而言之,试试这个:
function parseMinecraftColors($string) {
$string = htmlspecialchars($string, ENT_QUOTES, "UTF-8");
$string = preg_replace('/\xC2\xA7([0-9a-f])/i', '<span class="mc-color mc-$1">', $string, -1, $count) . str_repeat("</span>", $count);
return preg_replace('/\xC2\xA7([k-or])/i', '<span class="mc-$1">', $string, -1, $count) . str_repeat("</span>", $count);
}
或者这个:
function parseMinecraftColors($string) {
$string = htmlspecialchars($string, ENT_QUOTES, "UTF-8");
$string = preg_replace('/\xA7([0-9a-f])/iu', '<span class="mc-color mc-$1">', $string, -1, $count) . str_repeat("</span>", $count);
return preg_replace('/\xA7([k-or])/iu', '<span class="mc-$1">', $string, -1, $count) . str_repeat("</span>", $count);
}