Я настраиваю новый сервер и хочу полностью поддерживать UTF-8 в моем веб-приложении. Я пытался сделать это в прошлом на существующих серверах, и мне всегда приходилось прибегать к ISO-8859-1.
Где именно мне нужно установить кодировку/кодировки? Я знаю, что мне нужно настроить Apache, MySQL и PHP для этого - есть ли какой-то стандартный контрольный список, которому я могу следовать, или, возможно, устранить неполадки в случае несоответствия?
Это для нового сервера Linux, работающего под управлением MySQL 5, PHP, 5 и Apache 2.
Хранилище данных:
Укажите набор символов utf8mb4
для всех таблиц и текстовых столбцов в вашей базе данных. Это делает MySQL физически хранить и извлекать значения, закодированные изначально в UTF-8. Обратите внимание, что MySQL неявно использует utf8mb4
кодировку, если задана сортировка utf8mb4_*
(без какого-либо явного набора символов).
В более старых версиях MySQL (< 5.5.3) вам, к сожалению, придется просто использовать utf8
, который поддерживает только подмножество символов Unicode. Хотелось бы, чтобы я шутил.
Доступ к данным:
В вашем коде приложения (например, PHP) в любом используемом вами методе доступа к БД вам нужно установить кодировку соединений utf8mb4
. Таким образом, MySQL не выполняет преобразование из собственного UTF-8, когда он передает данные в ваше приложение и наоборот.
Некоторые драйверы предоставляют свой собственный механизм для настройки набора символов соединения, который обновляет собственное внутреннее состояние и сообщает MySQL о кодировке, которая будет использоваться в соединении. Это обычно предпочтительный подход. В PHP:
Если вы используете PDO уровень абстракции с помощью PHP & ge; 5.3.6 вы можете указать charset
в mysqli, вы можете вызвать set_charset()
:
$mysqli->set_charset('utf8mb4'); // object oriented style
mysqli_set_charset($link, 'utf8mb4'); // procedural style
Если вы застряли с обычным mysql, но, похоже, работает PHP & ge; 5.2.3 вы можете вызвать mysql_set_charset
.
Если драйвер не предоставляет свой собственный механизм для установки набора символов соединения, вам может потребоваться выдать запрос, чтобы сообщить MySQL, как ваше приложение ожидает, что данные в соединении будут закодированы: SET NAMES 'utf8mb4'
.
То же самое относится к utf8mb4
/utf8
, как указано выше.
Выход
Если ваше приложение передает текст другим системам, они также должны быть проинформированы о кодировке символов. В веб-приложениях браузер должен быть проинформирован о кодировке, в которой данные отправляются (через заголовки ответа HTTP или метаданные HTML).
В PHP вы можете использовать параметр default_charset
php.ini или вручную выпустить заголовок MIME Content-Type
самостоятельно, который просто больше работает, но имеет тот же эффект.
Ввод
К сожалению, вы должны проверить каждую полученную строку как действительную UTF-8, прежде чем пытаться ее сохранить или использовать в любом месте. PHP mb_check_encoding()
делает трюк, но вы должны использовать его религиозно. На самом деле это не так, поскольку вредоносные клиенты могут отправлять данные в любую кодировку, которую они хотят, и я не нашел трюка, чтобы заставить PHP сделать это для вас надежно.
Из моего чтения текущей спецификации HTML следующие субпалеты не нужны или даже не действительны для современного HTML. Я понимаю, что браузеры будут работать и отправлять данные в набор символов, указанный для документа. Однако, если вы ориентируетесь на более старые версии HTML (XHTML, HTML4 и т.д.), Эти пункты могут по-прежнему быть полезными:
accept-charset
ко всем тэгам <form>
: <form ... accept-charset="UTF-8">
.<form>
.Другие соображения кода:
Очевидно, что все файлы, которые вы будете обслуживать (PHP, HTML, JavaScript и т.д.), должны быть закодированы в действительном UTF-8.
Вам нужно убедиться, что каждый раз, когда вы обрабатываете строку UTF-8, вы делаете это безопасно. Это, к сожалению, тяжелая часть. Вероятно, вы захотите широко использовать расширение PHP mbstring
.
Встроенные строковые операции PHP по умолчанию не являются безопасными для UTF-8.Есть некоторые вещи, которые можно смело выполнять с обычными строковыми операциями PHP (например, конкатенация), но для большинства вещей вы должны использовать эквивалентную функцию mbstring
.
Чтобы узнать, что вы делаете (читайте: не испортите его), вам действительно нужно знать UTF-8 и как он работает на самом низком возможном уровне. Просмотрите любые ссылки из utf8.com для получения некоторых хороших ресурсов, чтобы узнать все, что вам нужно знать.
Я хотел бы добавить одну вещь к отличному ответу chazomaticus:
Не забудьте также тег META (например, или версию HTML4 или XHTML):
<meta charset="utf-8">
Это кажется тривиальным, но IE7 дал мне проблемы с этим раньше.
Я делал все правильно; база данных, соединение с базой данных и HTTP-заголовок Content-Type были настроены на UTF-8, и она отлично работала во всех других браузерах, но Internet Explorer по-прежнему настаивал на использовании "западноевропейской" кодировки.
Оказалось, что на странице отсутствует тег META. Добавление этого решения проблемы.
Edit:
У W3C фактически есть довольно большой раздел посвященный I18N. У них есть ряд статей, связанных с этой проблемой – описывая HTTP, (X) HTML и CSS сторону вещей:
Они рекомендуют использовать как HTTP-заголовок, так и метатег HTML (или объявление XML в случае использования XHTML как XML).
В дополнение к настройке default_charset
в php.ini вы можете отправить правильную кодировку с помощью header()
из вашего кода перед любым выходом:
header('Content-Type: text/html; charset=utf-8');
Работа с Unicode в PHP проста, если вы понимаете, что большинство строковых функций не работают с Unicode, а некоторые могут полностью блокировать строки. PHP считает, что "символы" имеют длину 1 байт. Иногда это нормально (например, explode()
ищет только последовательность байтов и использует его как разделитель, поэтому не имеет значения, какие фактические символы вы ищете). Но в других случаях, когда функция фактически предназначена для работы с символами, PHP не знает, что ваш текст имеет многобайтовые символы, которые находятся в Unicode.
Хорошая библиотека для проверки - phputf8. Это перезаписывает все "плохие" функции, чтобы вы могли безопасно работать с строками UTF8. Есть расширения, такие как расширение mbstring, которые тоже пытаются это сделать для вас, но я предпочитаю использовать библиотеку, потому что она более портативна (но я пишу продукты массового рынка, так что это важно для меня). Но phputf8 может использовать mbstring за кулисами, во всяком случае, для повышения производительности.
Старая тема, я знаю. Обнаружена проблема с кем-то, использующим PDO, и ответ должен был использовать это для строки подключения PDO:
$pdo = new PDO(
'mysql:host=mysql.example.com;dbname=example_db',
"username",
"password",
array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
Сайт, на котором я взял это, не работает, смог получить его с помощью кеша google.
$dbh->exec("set names utf8");
; я предпочитаю метод, представленный здесь). Btw. в руководстве по PHP есть также похожая заметка на это: php.net/manual/en/pdo.construct.php#96325 .
Прежде всего, если вы находитесь в < 5.3PHP, то нет. У тебя много проблем, чтобы справиться.
Я удивлен, что никто не упомянул библиотеку intl, которая имеет хорошую поддержку unicode, graphemes, операции с строкой, локализация и многие другие, см. ниже.
Я приведу некоторую информацию о поддержке unicode в PHP с помощью slides Элизабет Смит в PHPBenelux'14
Хорошо:
Плохо:
stream_filter_append($fp, 'convert.iconv.ISO-2022-JP/EUC-JP')
Я обновлю этот ответ, если что-то изменит добавленные функции и так далее.
--with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd
.
В моем случае я использовал mb_split
, который использует регулярное выражение. Поэтому мне также пришлось вручную убедиться, что кодировка регулярного выражения была utf-8, выполнив mb_regex_encoding('UTF-8');
В качестве дополнительной заметки я также обнаружил, запустив mb_internal_encoding()
, что внутренняя кодировка не была utf-8, и я изменил ее, запустив mb_internal_encoding("UTF-8");
.
Недавно я обнаружил, что использование strtolower()
может вызвать проблемы, когда данные усекаются после специального символа.
Решение заключалось в использовании
mb_strtolower($string, 'UTF-8');
mb_ использует MultiByte. Он поддерживает больше символов, но в целом немного медленнее.
Единственное, что я хотел бы добавить к этим замечательным ответам, - это подчеркнуть сохранение ваших файлов в кодировке utf8, я заметил, что браузеры принимают это свойство за установку utf8 в качестве кодировки кода. Любой достойный текстовый редактор покажет вам это, например Notepad ++ имеет пункт меню для подделки файлов, он показывает текущую кодировку и позволяет вам ее изменить. Для всех моих php файлов я использую utf8 без спецификации.
Некоторое время назад у меня кто-то попросил меня добавить поддержку utf8 для приложения php/mysql, разработанного кем-то еще, я заметил, что все файлы были закодированы в ANSI, поэтому мне пришлось использовать ICONV для преобразования всех файлов, изменения таблиц базы данных для использования команды utf8 charset и utf8_general_ci, добавьте "SET NAMES utf8" на уровень абстракции базы данных после подключения (если используете 5.3.6 или более раннее, иначе вам нужно использовать charset = utf8 в строке подключения) и изменить строковые функции для использования функциональные функции многобайтовой строки php эквивалентны.
Я только что прошел ту же проблему и нашел хорошее решение в руководствах PHP.
Я изменил всю свою кодировку файла на UTF8, а затем по умолчанию в моем соединении. Это позволило решить все проблемы.
if (!$mysqli->set_charset("utf8")) {
printf("Error loading character set utf8: %s\n", $mysqli->error);
} else {
printf("Current character set: %s\n", $mysqli->character_set_name());
}
set_charset('utf8mb4')
не сработал, но >set_charset("utf8")
сработал, и это не было показано в других ответах.
set_charset("utf8")
может работать, но будет вести себя по-разному (см. Замечания о разнице между utf8
и utf8mb4
и историей версий mysql). Используйте utf8
если вам нужно И ТОЛЬКО если вы знаете, что делаете !
В PHP вам нужно либо использовать функции multibyte, либо включить mbstring.func_overload. Таким образом, такие вещи, как strlen, будут работать, если у вас есть символы, которые принимают более одного байта.
Вам также потребуется определить набор символов ваших ответов. Вы можете использовать AddDefaultCharset, как указано выше, или написать PHP-код, который возвращает заголовок. (Или вы можете добавить метку META в свои HTML-документы.)
Хорошая цель - с самого начала - основываясь на характере вашего сайта, я нашел много ресурсов по этому поводу в Googling - вы, конечно, не первый в этом разбираетесь.
Предполагается, что мистический PHP6 должен все это выпрямиться, верно?
Вы можете в значительной степени настроить utf-8 как глобальную кодировку по умолчанию для mysql на уровне сервера, и она по умолчанию будет правильно соответствовать более гранулированным уровням.
Поддержка Unicode в PHP по-прежнему огромна. Хотя он способен преобразовывать строку ISO8859 (которая используется внутри нее) в utf8, ей не хватает возможности работать с строками unicode изначально, что означает, что все функции обработки строк будут калечить и испортить ваши строки. Поэтому вам нужно либо использовать отдельную библиотеку для правильной поддержки utf8, либо самостоятельно переписать все функции обработки строк.
Легкая часть - это просто указание кодировки в заголовках HTTP и в базе данных и т.д., но ничто из этого не имеет значения, если ваш PHP-код не выводит допустимый UTF8. Это сложная часть, и PHP дает вам практически никакой помощи. (Я думаю, что PHP6 должен исправить худшее из этого, но это все еще вдалеке)
Если вы хотите, чтобы сервер MySQL решал набор символов, а не PHP как клиент (старое поведение, предпочтительнее, на мой взгляд), попробуйте добавить skip-character-set-client-handshake
к my.cnf
под [mysqld]
и перезапустить mysql
.
Это может вызвать проблемы, если вы используете что-то другое, кроме UTF8.
Верхний ответ отличный. Вот что я должен был сделать на обычной настройке debian/php/mysql:
// storage
// debian. apparently already utf-8
// retrieval
// the mysql database was stored in utf-8,
// but apparently php was requesting iso. this worked:
// ***notice "utf8", without dash, this is a mysql encoding***
mysql_set_charset('utf8');
// delivery
// php.ini did not have a default charset,
// (it was commented out, shared host) and
// no http encoding was specified in the apache headers.
// this made apache send out a utf-8 header
// (and perhaps made php actually send out utf-8)
// ***notice "utf-8", with dash, this is a php encoding***
ini_set('default_charset','utf-8');
// submission
// this worked in all major browsers once apache
// was sending out the utf-8 header. i didnt add
// the accept-charset attribute.
// processing
// changed a few commands in php, like substr,
// to mb_substr
Это все!
Размещено как сообщество wiki:
Для пользователей WordPress:
Sidenote: вопрос был отменен. Сообщение было взято из:
и другое редактирование https://stackoverflow.com/revisions/35671546/6
Частичное сообщение:
У меня есть сайт wordpress, который я установил на своем локальном хосте. Я только что загрузил его на мой хостинг и импортировал базу данных, но все они отображаются как.
Решение из OP:
Для всех, у кого есть эта проблема, ниже это исправлено для меня. Он не был связан с базой данных.
Требуется обновление wp-config.php. Я изменил define('DB_CHARSET', 'utf8mb4');
на define('DB_CHARSET', 'utf8');