Как правильно обрабатывать UTF-8 в PHP? - PullRequest
3 голосов
/ 01 ноября 2011

Я пытаюсь заставить нашу систему чата поддерживать 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] => ???
)

Что мне нужно сделать, чтобы сделать эту работу?

Ответы [ 2 ]

2 голосов
/ 01 ноября 2011
$_POST['message'], => [0] => %C3%AE%C3%BB%C3%B4%C3%B3

Вы зашифровали URL-адрес своего ввода. Суперглобальные переменные GET / POST / REQUEST уже позаботились о входных строках декодирования 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. В качестве альтернативы вы можете убедить Блокнот прочитать файл Unicode, сохранив его как UTF-16 или UTF-8 и включив метку порядка байтов в начале. (Включение спецификации в файл UTF-8 является своего рода неправильным, но многие инструменты в мире Microsoft делают это.)

2 голосов
/ 01 ноября 2011

Идти UTF8 по всему стеку:

  • Таблицы базы данных
  • Подключение к базе данных
  • Настройка набора символов PHP по умолчанию
  • Строковые функции

Таблицы базы данных:

Установите для сопоставления БД значение utf8_unicode_ci.Установите для всех полей text / varchar значение utf8_unicode_ci.Установите соединение с базой данных как UTF-8, выполнив следующий запрос:

SET NAMES 'utf8'

PHP Charset

Использование:

ini_set('default_charset', 'utf-8'); 

PHP String Функции

Некоторые строковые функции PHP не являются бинарно-безопасными, поэтому вам нужно использовать эквиваленты mb_ *.

например mb_strlen вместо strlen

HTML:

Установите кодировку с метатегом:

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