打印Unicode字符PHP

13
我有一个数据库,其中存储了带有Unicode字符的视频游戏名称,但是当我将它们打印到HTML响应时,我无法正确转义这些Unicode字符。例如,当我打印所有名称类似于“Uncharted”的游戏时,我会得到以下结果:
Uncharted: Drake's Fortuneâ„¢
Uncharted 2: Among Thievesâ„¢
Uncharted 3: Drake's Deceptionâ„¢

但它应该显示这个:
Uncharted: Drake's Fortune™
Uncharted 2: Among Thieves™
Uncharted 3: Drake's Deception™

我运行了一个快速的JavaScript转义函数来查看是哪个Unicode字符,并发现它是\u2122
如果我可以正确显示字符,那么我不会对字符串中的每个字符进行完全转义。我的猜测是以某种方式找到字符串中每个字符的十六进制表示,并让PHP呈现Unicode字符,如下所示:
print "&#x2122";

请指导我如何最好地对字符串进行Unicode转义,以便使其适用于HTML。我之前做过类似于JavaScript的操作,但是JavaScript有一个内置的转义和反转义函数。
然而,我不知道任何PHP具有类似功能的函数。我已经阅读了关于ord函数的内容,但它只返回给定字符的ASCII字符代码,因此无法正确显示™™。我希望这个函数足够通用,可以应用于包含有效Unicode字符的任何字符串。
4个回答

18

看起来你在内部使用UTF-8编码的字符串,PHP可以正确输出,但浏览器无法自动检测编码(它决定使用ISO 8859-1或其他编码)。

最好的方法是通过发送相应的HTTP标头告诉浏览器正在使用UTF-8:

<em>告诉浏览器正在使用UTF-8</em>

header("content-type: text/html; charset=UTF-8");  
然后,您可以保留其余的代码不变,无需对实体进行HTML编码或创建其他混乱。
如果您想要,还可以通过使用<meta>标签在生成的HTML中声明编码:
  • <meta http-equiv=Content-Type content="text/html; charset=UTF-8"> 适用于HTML <=4.01
  • <meta charset="UTF-8"> 适用于HTML5
HTTP头优先于<meta>标签,但后者在将HTML保存到硬盘上并然后本地读取时可能会有用。

@ViktorJoras请检查您的PHP脚本和/或服务器端字符串资源是否采用UTF-8编码。 - Alex Shesterov

13

我花了很多时间来寻找一种更好的方法,只是打印出unicode代码的等效字符,但我发现的方法都没有起作用或者非常复杂。

话虽如此,JSON可以使用语法“\u[unicode_code]”来表示Unicode字符,因此:

echo json_decode('"\u00e1"'); 

将打印出相应的Unicode字符,本例中为:á。

P.D. 注意单引号和双引号。如果两者都不放置,则不起作用。


8
// PHP 7.0
var_dump(
    IntlChar::chr(0x2122),
    IntlChar::chr(0x1F638)
);

var_dump(
    utf8_chr(0x2122),
    utf8_chr(0x1F638)
);

function utf8_chr($cp) {

    if (!is_int($cp)) {
        exit("$cp is not integer\n");
    }

    // UTF-8 prohibits characters between U+D800 and U+DFFF
    // https://tools.ietf.org/html/rfc3629#section-3
    //
    // Q: Are there any 16-bit values that are invalid?
    // http://unicode.org/faq/utf_bom.html#utf16-7

    if ($cp < 0 || (0xD7FF < $cp && $cp < 0xE000) || 0x10FFFF < $cp) {
        exit("$cp is out of range\n");
    }

    if ($cp < 0x10000) {
        return json_decode('"\u'.bin2hex(pack('n', $cp)).'"');
    }

    // Q: Isn’t there a simpler way to do this?
    // http://unicode.org/faq/utf_bom.html#utf16-4
    $lead = 0xD800 - (0x10000 >> 10) + ($cp >> 10);
    $trail = 0xDC00 + ($cp & 0x3FF);

    return json_decode('"\u'.bin2hex(pack('n', $lead)).'\u'.bin2hex(pack('n', $trail)).'"');
}

7

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接