Web

Об UTF-8

Я настраиваю новый сервер и хочу полностью поддерживать UTF-8 в своем веб-приложении. Я пробовал это в прошлом на существующих серверах, и мне всегда приходилось возвращаться к другим кодировкам.

Где именно мне нужно установить кодировку? Я знаю, что для этого мне нужно настроить Apache, MySQL и PHP - есть ли какой-нибудь стандартный способ, которому я могу следовать, или, возможно, устранить неполадки, где возникают ошибки?

 

Ответ 1

Хранение данных:

  • Укажите utf8mb4 набор символов для всех таблиц и текстовых столбцов в вашей базе данных. Это заставит MySQL физически хранить и извлекать значения, изначально закодированные в UTF-8. Обратите внимание, что MySQL будет неявно использовать utf8mb4 кодировку, если указана utf8mb4_* (без явного набора символов).

  • В более старых версиях MySQL (<5.5.3) вам, к сожалению, придется использовать простой код utf8, который поддерживает только подмножество символов Unicode.

 

Доступ к данным:

  • В коде вашего приложения (например, PHP), в любом методе доступа к БД, который вы используете, вам необходимо установить кодировку соединения на utf8mb4. Таким образом, MySQL не будет выполнять преобразование из собственного UTF-8, когда передает данные вашему приложению, и наоборот.

  • Некоторые драйверы предоставляют свой собственный механизм для настройки кодировки, который обновляет внутреннее состояние и сообщает MySQL о кодировке, которая будет использоваться при соединении - обычно это предпочтительный подход. В PHP:

    • Если вы используете уровень абстракции PDO с PHP ≥ 5.3.6, вы можете указать charset в DSN:

 

 $dbh = new PDO('mysql:charset=utf8mb4');

 

  • Если вы используете mysqli, вы можете вызвать set_charset():

$mysqli->set_charset('utf8mb4');

mysqli_set_charset($link, 'utf8mb4');

 

  • Если вы используете PHP ≥ 5.2.3, вы можете вызвать mysql_set_charset.

  • Если драйвер не предоставляет свой собственный механизм для установки кодировки, возможно, придется вызвать запрос , чтобы указать MySQL , как ваше приложение использует символы кодировки: SET NAMES 'utf8mb4'.

  • В отношении utf8mb4/tf8 применяется тот же механизм, который был рассмотрен выше.

 

При выводе:

  • Если ваше приложение передает текст в другие программы/системы, они также должны быть проинформированы о кодировке символов. В веб-приложениях браузер должен быть проинформирован о кодировке, в которой представлены данные (через заголовки ответа HTTP или метаданные HTML).

  • В PHP вы можете использовать параметр default_charset в php.ini или вручную через Content-Type, который создает заголовок MIME самостоятельно, что требует больше работы, но дает тот же эффект.

  • При кодировании вывода с помощью функции json_encode() добавьте JSON_UNESCAPED_UNICODE в качестве второго параметра.

 

Входные значения:

  • К сожалению, вы должны проверять каждую полученную строку как действительную UTF-8, прежде чем пытаться ее сохранить или использовать где-либо. В PHP функция mb_check_encoding() делает свое дело, но вы должны использовать ее постоянно. На самом деле нет никакого способа обойти эту проблему, поскольку недобросовестные клиенты могут отправлять данные в любой кодировке, которой они хотят, и я не нашел способа, избежать этого.

  • Из того, что известно о текущей спецификации HTML, следующие подпункты не являются обязательными для современного HTML. Насколько я понимаю, браузеры будут работать и отправлять данные в кодировке, указанной для документа. Однако, если вы ориентируетесь на более старые версии HTML (XHTML, HTML4 и т. д.), эти моменты все еще могут быть полезны:

    • Только для HTML до HTML5 : Если вы хотите, чтобы все данные, отправляемые вам браузерами, были в UTF-8,.то единственным способом надежно сделать это является добавить accept-charset атрибут для всех тегов <form><form ... accept-charset="UTF-8">.

    • Только для HTML до HTML5 : обратите внимание, что в спецификации W3C HTML говорится, что клиенты "должны" по умолчанию отправлять формы обратно на сервер в любой кодировке, которую обслуживает сервер, но это, по-видимому, только рекомендация, следовательно, необходимости в этом нет.

 

Другие соображения по коду:

  • Очевидно, что все файлы, которые вы будете использовать (PHP, HTML, JavaScript и т. д.), должны быть закодированы в UTF-8.

  • Вы должны быть уверены, что каждый раз, когда вы обрабатываете строку UTF-8, вы делаете это безопасно. К сожалению, это самая сложная часть. Наиболее правильный способ сделать это - использовать mbstring расширение PHP .

  • Встроенные строковые операции PHP по умолчанию не поддерживают UTF-8. Есть некоторые задачи, которые можно безопасно делать с помощью обычных строковых операций PHP (например, конкатенация), но для большинства задач вы должны использовать эквивалентную функцию mbstring.

  • Чтобы знать, что вы делаете (читай: не испортить), вам действительно нужно знать UTF-8 и то, как он работает на самом низком уровне. Ознакомьтесь с документацией по UTF-8 на любом доступном ресурсе.

 

Ответ 2

В дополнение к настройке default_charset в php.ini вы можете отправить правильную кодировку, используя header()  из вашего кода, перед любым выводом:

header('Content-Type: text/html; charset=utf-8');

 

Работать с Unicode в PHP легко, если вы понимаете, что большинство строковых функций не работают с Unicode, а некоторые могут полностью искажать строки. PHP считает, что "символы" строки имеют длину 1 байт. Иногда это нормально (например, explode() ищет только последовательность байтов и использует ее в качестве разделителя, поэтому не имеет значения, какие именно символы вы ищете). Но в других случаях, когда функция действительно предназначена для работы с символами, PHP не знает, что в вашем тексте есть многобайтовые символы, которые можно использовать только с Unicode.

Хорошая библиотека для этого - phputf8.  Она переопределяет все функции, чтобы вы могли безопасно работать со строками UTF-8. Существуют расширения, такие как mbstring, которые также пытаются сделать это за вас, но я предпочитаю использовать библиотеку, потому что она более портативна. phputf8 в любом случае может использовать mbstring за кулисами для повышения производительности.

 

Ответ 3

В моем случае я использовал mb_split, который использует регулярное выражение. И для этого мне пришлось вручную убедиться, что кодировка регулярного выражения была utf-8, выполнив mb_regex_encoding('UTF-8');

Также добавлю, что, запустив, mb_internal_encoding(),  я обнаружил, что внутренняя кодировка не является utf-8, и мне пришлось исправить это, запустив mb_internal_encoding("UTF-8");.

 

Ответ 4

Единственное, что можно добавить к предыдущим ответам, - это подчеркнуть, что необходимо обязательно сохранять ваши файлы в кодировке utf-8. Я заметил, что браузеры принимают это свойство, и не устанавливают utf-8 в качестве кодировки кода. Любой приличный текстовый редактор покажет вам это, например, в Notepad ++ есть пункт меню где показывается текущая кодировка и есть возможность изменять ее. Для всех моих файлов php я использую utf-8 по умолчанию.

Некоторое время назад меня попросили добавить поддержку utf-8 в приложение php/mysql, разработанное кем-то другим. Я заметил, что все файлы были закодированы в ANSI, поэтому мне пришлось использовать ICONV для преобразования всех файлов, изменить таблицы базы данных, добавить 'SET NAMES utf-8' в уровень абстракции базы данных. Также пришлось изменить все строковые функции, чтобы использовать эквивалент многобайтовых строковых функций в php.

Схожие статьи

Web

Что такое stdClass в PHP?

Web

Допустимо ли использование коротких тегов PHP?

Web

Как преобразовать серию «родитель-потомок» в иерархическое дерево

Web

Как предотвратить SQL-инъекцию в PHP?