Я настраиваю новый сервер и хочу полностью поддерживать UTF-8 в своем веб-приложении. Я пробовал это в прошлом на существующих серверах, и мне всегда приходилось прибегать к ISO-8859-1.
Где именно мне нужно установить кодировку / кодировку? Я знаю, что для этого мне нужно настроить Apache, MySQL и PHP - есть ли какой-нибудь стандартный контрольный список, которому я могу следовать, или, возможно, устранить неполадки, где возникают несоответствия?
Это для нового сервера Linux, на котором работают MySQL 5, PHP, 5 и Apache 2.
Вот введение в кодировки в целом и кодировки в PHP в частности: Что абсолютно необходимо знать каждому программисту о кодировках и наборах символов для работы с текстом
Некоторые недавние обсуждение PHP 7 указывают на то, что нет никаких изменений в позиции "официально заброшенной" в 2010 году ... Есть что-нибудь еще о "PHP7 и UTF-8"?
Это обычная проблема. Но быстрого решения нет, вам придется настроить utf-8 для каждого из них отдельно - MySQL 5, PHP5 ИЛИ Apache2.






В PHP вам нужно либо использовать многобайтовые функции, либо включить mbstring.func_overload. Таким образом, такие вещи, как strlen, будут работать, если у вас есть символы, занимающие более одного байта.
Вам также необходимо определить набор символов ваших ответов. Вы можете использовать AddDefaultCharset, как указано выше, или написать PHP-код, который возвращает заголовок. (Или вы можете добавить тег META в свои HTML-документы.)
Отличный совет о настройке func_overload - позволяет минимизировать модификацию существующего кода.
Просто будьте осторожны - некоторый код может фактически полагаться на однобайтовую природу стандартных строковых функций.
Важно отметить, что функция mbstring.func_overload устарела с PHP 7.2 из-за проблем, отмеченных в комментарии @ JW выше. Итак, лучший совет: да, вам обязательно следует использовать функции mbstring, но не используйте функцию перегрузки, чтобы стандартные функции работали как многобайтовые.
В дополнение к настройке 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 за кулисами для повышения производительности.
Поддержка Unicode в PHP по-прежнему представляет собой огромный беспорядок. Хотя он способен преобразовывать строку ISO8859 (которую он использует внутри) в utf8, ему не хватает возможности работать со строками Unicode изначально, что означает, что все функции обработки строк будут искажать и повреждать ваши строки. Поэтому вам нужно либо использовать отдельную библиотеку для правильной поддержки utf8, либо самостоятельно переписать все функции обработки строк.
Легкая часть - это просто указать кодировку в заголовках HTTP, в базе данных и т. д., Но все это не имеет значения, если ваш PHP-код не выводит действительный UTF8. Это сложная часть, и PHP здесь практически не поможет. (Я думаю, что PHP6 должен исправить самое худшее из этого, но до этого еще далеко)
Хочу добавить в отличный ответ chazomaticus одну вещь:
Не забудьте и о теге META (например, его версия HTML4 или XHTML):
<meta charset = "utf-8">
Это кажется тривиальным, но IE7 и раньше доставлял мне проблемы с этим.
Я все делал правильно; база данных, соединение с базой данных и HTTP-заголовок Content-Type были настроены на UTF-8, и он отлично работал во всех других браузерах, но Internet Explorer по-прежнему настаивал на использовании «западноевропейской» кодировки.
Оказалось, что на странице отсутствует метатег. Добавление, которое решило проблему.
Редактировать:
W3C на самом деле имеет довольно большой раздел посвященный I18N. У них есть ряд статей, связанных с этой проблемой - описывающих аспекты HTTP, (X) HTML и CSS:
Они рекомендуют использовать как заголовок HTTP, так и метатег HTML (или объявление XML в случае, если XHTML используется как XML).
Главный ответ - отлично. Вот что мне пришлось сделать при обычной настройке 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
это все !
В моем случае я использовал mb_split, который использует регулярное выражение. Поэтому мне также пришлось вручную убедиться, что кодировка регулярного выражения была utf-8, выполнив mb_regex_encoding('UTF-8');
В качестве примечания, я также обнаружил, запустив mb_internal_encoding(), что внутренняя кодировка не является utf-8, и я изменил это, запустив mb_internal_encoding("UTF-8");.
Я обнаружил проблему с кем-то, использующим 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.
Если посмотреть на это немного дальше, это необходимо только для версий PHP до 5.3.6. См. Также: http://stackoverflow.com/a/4361485/2286722 (хотя они используют отдельный $dbh->exec("set names utf8");; я предпочитаю метод, представленный здесь). Кстати. об этом также есть аналогичное примечание в виде комментария в руководстве по PHP: php.net/manual/en/pdo.construct.php#96325.
См. Также Ответ Палека на PDO + MySQL и сломанная кодировка UTF-8.
Вы спасли мою жизнь.
Недавно я обнаружил, что использование strtolower() может вызвать проблемы, когда данные обрезаются после специального символа.
Решение заключалось в использовании
mb_strtolower($string, 'UTF-8');
mb_ uses MultiByte. It supports more characters but in general is a little slower.
Прежде всего, если у вас <5.3PHP, тогда нет. У вас есть масса проблем, которые нужно решить.
Я удивлен, что никто не упомянул библиотеку международный, которая хорошо поддерживает Юникод, графемы, строковые операции, локализация и многие другие, см. Ниже.
Я процитирую некоторую информацию о поддержке Unicode в PHP от Элизабет Смитслайды в PHPBenelux'14
Хорошо:
Плохой:
stream_filter_append($fp, 'convert.iconv.ISO-2022-JP/EUC-JP')Я обновлю этот ответ, если что-то изменится, добавлены функции и так далее.
Да, верно. Mysqli и PDO могут использовать свои собственные драйверы. Также они могут использовать драйвер mysqlnd, если вы будете компилировать php с опциями --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd.
Единственное, что я бы добавил к этим удивительным ответам, - это подчеркнуть сохранение ваших файлов в кодировке utf8. Я заметил, что браузеры принимают это свойство, а не устанавливают utf8 в качестве кодировки кода. Любой приличный текстовый редактор покажет вам это, например, в Notepad ++ есть пункт меню для включения файла, он показывает текущую кодировку и позволяет изменять ее. Для всех моих файлов php я использую utf8 без спецификации.
Некоторое время назад кто-то попросил меня добавить поддержку utf8 для приложения php / mysql, разработанного кем-то другим, я заметил, что все файлы были закодированы в ANSI, поэтому мне пришлось использовать ICONV для преобразования всех файлов, изменить таблицы базы данных, чтобы использовать Кодировка utf8 и сопоставление utf8_general_ci, добавьте 'SET NAMES utf8' на уровень абстракции базы данных после подключения (при использовании версии 5.3.6 или более ранней версии, в противном случае вы должны использовать charset = utf8 в строке подключения) и измените строковые функции для использования многобайтовой версии php. эквивалент строковых функций.
Если вы хотите, чтобы набор символов определял сервер MySQL, а не PHP в качестве клиента (старое поведение; на мой взгляд, предпочтительнее), попробуйте добавить skip-character-set-client-handshake в ваш my.cnf под [mysqld] и перезапустите mysql.
Это может вызвать проблемы, если вы используете что-либо, кроме UTF8.
Я только что столкнулся с той же проблемой и нашел хорошее решение в руководствах по 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") работал, и это фактически не было показано в других ответах.
@FunkFortyNiner Остерегайтесь: set_charset("utf8") может работать, но будет вести себя по-другому (см. Примечания о разнице между utf8 и utf8mb4 и историю версий mysql). Используйте utf8если тебе нужно И ТОЛЬКО если ты знаешь что делаешь!
Решение 5 звезд, я читал текстовый файл построчно и получал? для каждого символа я сделал save-as вместо ansi использовал utf8. благодаря.
Если вам нужно решение mysql, у меня были аналогичные проблемы с двумя моими проектами после миграции сервера. После поиска и опробования множества решений я столкнулся с этим / ничего до того, как это сработало):
mysqli_set_charset($con,"utf8");
После добавления этой строки в мой файл конфигурации все работает нормально!
Я нашел это решение https://www.w3schools.com/PHP/func_mysqli_set_charset.asp, когда искал вставку из html-запроса
удачи!
Просто примечание:
Вы столкнулись с проблемой, что ваши нелатинские символы отображаются как ?????????, вы задали вопрос, и он был закрыт ссылкой на этот канонический вопрос, вы перепробовали все, и что бы вы ни делали, вы все равно получаете ?????????? от MySQL.
В основном это связано с тем, что вы тестируете ваши старые данные, который был вставлен в базу данных с использованием неправильной кодировки и преобразован и сохранен в фактически символы вопросительного знака ?. Это означает, что вы навсегда потеряли исходный текст, и что бы вы ни пытались, вы получите ???????.
Повторное применение того, что вы узнали из ответов на этот вопрос, на свежих данных может решить вашу проблему.
в connection.php: mysqli_set_charset ($ con, «utf8»); и в сопоставлении sql utf = 8
Вот обзор всех возможных ошибок кодирования: sebastianviereck.de/en/…