我正在努力让我们的聊天系统支持UTF-8,但我失败了。如果,在客户端,我发送以下消息,通过encodeURIComponent
:
并将其放在PHP端:
error_log(print_r(array(
$_POST['message'],
urldecode($_POST['message']),
rawurldecode($_POST['message']),
utf8_decode($_POST['message']),
utf8_decode(urldecode($_POST['message'])),
utf8_decode(rawurldecode($_POST['message']))
), true));
这是我的错误日志中的输出:
Array
(
[0] => %C3%AE%C3%BB%C3%B4%C3%B3
[1] => îûôó
[2] => îûôó
[3] => %C3%AE%C3%BB%C3%B4%C3%B3
[4] => îûôó
[5] => îûôó
)
所以一切都很好。但是,如果我使用这些,都是从维基百科复制的(分别是俄语和日语页面):
这一切都到了地狱!
Array
(
[0] => %D1%80%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B9%20%D1%8F%D0%B7%D1%8B%D0%BA
[1] => руÑÑкий Ñзык
[2] => руÑÑкий Ñзык
[3] => %D1%80%D1%83%D1%81%D1%81%D0%BA%D0%B8%D0%B9%20%D1%8F%D0%B7%D1%8B%D0%BA
[4] => ??????? ????
[5] => ??????? ????
)
Array
(
[0] => %E6%97%A5%E6%9C%AC%E8%AA%9E
[1] => 日本語
[2] => 日本語
[3] => %E6%97%A5%E6%9C%AC%E8%AA%9E
[4] => ???
[5] => ???
)
我需要做些什么来完成这项工作?
答案 0 :(得分:2)
在整个堆栈中使用UTF8:
将db collation设置为utf8_unicode_ci
将所有text / varchar字段设置为utf8_unicode_ci
通过执行以下查询将数据库连接设置为UTF-8:
SET NAMES 'utf8'
使用:
ini_set('default_charset', 'utf-8');
某些PHP字符串函数不是二进制安全的,因此您需要使用mb_ *等效项。
e.g。 mb_strlen
代替strlen
使用元标记设置字符集:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
答案 1 :(得分:2)
$_POST['message'], => [0] => %C3%AE%C3%BB%C3%B4%C3%B3
您对输入进行了过度URL编码。 GET / POST / REQUEST超级全局已经在必要时处理URL解码输入字符串,您不需要手动对它们进行URL解码。
查看导致此请求的任何内容(XMLHttpRequest?)并删除对encodeURIComponent()
的多余调用。例如,如果您使用jQuery ajax()
并将POST数据作为对象传递,jQuery将为您调用encodeURIComponent()
,您也不需要自己执行此操作。
urldecode($_POST['message']), => îûôó
这是UTF-8误解为Windows代码页1252(西欧,类似于ISO-8859-1)。
您很可能已成功将UTF-8字节保存到日志文件中,但无论您正在读取日志文件,都没有意识到它应该呈现为UTF-8。
utf8_decode(urldecode($_POST['message'])), => îûôó
这只能起作用,因为您用来测试它的字符也存在于代码页1252中。utf8_decode
被误导地命名;它实际上做的是将UTF-8字节序列转换为表示相同字符串的ISO-8859-1字节序列。您通常希望使用UTF-8而不是ISO-8859-1,因此通常应避免使用utf8_decode。
русский язык => ??????? ????
可理解:代码页1252中不存在西里尔字符。
假设您正在将error_log输出发送到文件,并尝试读取该文件,请坚持使用普通的UTF-8字节,并在一个体面的文本编辑器中读取您的日志,以便您查看和选择编码;理想情况下是默认为UTF-8的现代版本。或者,您可以通过保存为UTF-16或UTF-8并在开头包含字节顺序标记来说服记事本读取Unicode文件。 (在UTF-8文件中包含BOM是错误的,但Microsoft世界中的许多工具都是这样做的。)