打印Unicode字符PHP

时间:2013-07-09 03:29:23

标签: php unicode html-escape-characters

我有一个数据库,用于存储带有Unicode字符的视频游戏名称,但我无法弄清楚如何在将这些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有一个用于escape和unescape的内置函数。

但我不知道任何类似功能的PHP函数。我已经阅读了ord函数,但它只返回给定字符的ASCII字符代码,因此™™的显示不正确。我希望这个函数足够通用,可以应用于任何包含有效Unicode字符的字符串。

4 个答案:

答案 0 :(得分:18)

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

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

header("content-type: text/html; charset=UTF-8");  

然后,您可以按原样保留其余代码,而不必使用html编码实体或创建其他混乱。

如果需要,您可以另外使用<meta>标记在生成的HTML中声明编码:

  • <meta http-equiv=Content-Type content="text/html; charset=UTF-8">适用于HTML&lt; = 4.01
  • <meta charset="UTF-8"> HTML5

HTTP标头优先于<meta>标签,但如果将HTML保存到HD然后在本地读取,则后者可能很有用。

答案 1 :(得分:10)

我花了很多时间试图找到更好的方法来打印unicode代码的等效char,而我发现的方法不起作用或者它只是非常复杂。

这就是说,JSON能够使用语法“\ u [unicode_code]”来表示unicode字符,然后:

echo json_decode('"\u00e1"'); 

将打印等效的unicode char,在这种情况下:á。

Pd积。请注意简单和双引号。如果你不放两者都不行。

答案 2 :(得分:6)

试试这个:

echo htmlentities("Uncharted: Drakes Fortune™ \n", ENT_QUOTES, "UTF-8");

来自:http://php.net/htmlentities

答案 3 :(得分:3)

// 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)).'"');
}