如何在PHP中正确处理UTF-8?

如何在PHP中正确处理UTF-8?,php,javascript,encoding,utf-8,encodeuricomponent,Php,Javascript,Encoding,Utf 8,Encodeuricomponent,我试图让我们的聊天系统支持UTF-8,但失败了。如果在客户端,我通过encodeURIComponent发送以下消息: î 把这个放在PHP端: error_log(print_r(array( $_POST['message'], urldecode($_POST['message']), rawurldecode($_POST['message']), utf8_decode($_POST['message']), utf8_decode(urld

我试图让我们的聊天系统支持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] => ???
)

我需要做什么才能使它工作?

在整个堆栈中使用UTF8:

  • 数据库表
  • 数据库连接
  • PHP默认字符集设置
  • 字符串函数
数据库表: 将数据库排序规则设置为
utf8\u unicode\u ci

将所有文本/varchar字段设置为
utf8\u unicode\u ci

通过执行以下查询,将数据库连接设置为UTF-8:

SET NAMES 'utf8'
PHP字符集 使用:

PHP字符串函数 有些PHP字符串函数不是二进制安全的,因此需要使用mb_*等价物

e、 g.
mb_strlen
而不是
strlen

HTML: 使用元标记设置字符集:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

您的输入已经过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\U decode
的名称有误导性;它实际做的是将UTF-8字节序列转换为ISO-8859-1字节序列,以表示相同的字符串。您通常希望在UTF-8而不是ISO-8859-1中工作,因此通常应避免utf8_解码

русский язык => ??????? ????
可以理解:代码页1252中不存在西里尔字符


假设您正在将错误日志输出发送到一个文件,并尝试读取该文件,请坚持使用纯UTF-8字节,并在一个体面的文本编辑器中读取日志,该编辑器允许您查看和选择编码;理想情况下是一个默认为UTF-8的现代版本。或者,您可以通过另存为UTF-16或UTF-8并在开始处包含字节顺序标记来说服记事本读取Unicode文件。(在UTF-8文件中包含BOM有点错误,但Microsoft世界中的许多工具都这样做。)

不要重复相同的答案。。。像这样的答案已经有很多了那你为什么不把Aistina和其中一个联系起来呢?同时,我会提供一些帮助。可能的重复只是为了以防万一:也许你的日志文件编码和显示字体不处理utf8?如果你把日语和俄语直接放在PHP端,它能工作吗?你确定javascript发送端的内容被破坏了吗?先生,你真是太棒了。这个答案的每一点都很准确:)成功了,非常感谢!
utf8_decode(urldecode($_POST['message'])), => îûôó
русский язык => ??????? ????