Я настраиваю новый сервер и хочу полностью поддерживать UTF-8 в моем веб-приложении. Я пытался сделать это в прошлом на существующих серверах, и мне всегда приходилось прибегать к ISO-8859-1.
Где именно мне нужно установить кодировку / кодировки? Я знаю, что для этого мне нужно настроить Apache, MySQL и PHP - есть ли какой-нибудь стандартный контрольный список, которому я могу следовать, или, возможно, устранить неполадки в случае несоответствия?
Это для нового сервера Linux, работающего под управлением MySQL 5, PHP, 5 и Apache 2.
utf-8
каждый из них отдельно - 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 ≥ 5.3.6, вы можете указать
charset
в DSN :Если вы используете mysqli , вы можете позвонить
set_charset()
:Если вы застряли с обычным mysql, но случайно запустили PHP ≥ 5.2.3, вы можете позвонить
mysql_set_charset
.Если драйвер не предоставляет свой собственный механизм для установки набора символов соединения, возможно , придется выдать запрос , чтобы сказать MySQL , как ваше приложение ожидает данные о связи должны быть закодированы:
SET NAMES 'utf8mb4'
.То же самое касается
utf8mb4
/utf8
применяется, как указано выше.Выход :
Если ваше приложение передает текст в другие системы, они также должны быть проинформированы о кодировке символов. В веб-приложениях браузер должен быть проинформирован о кодировке, в которой отправляются данные (через заголовки ответа HTTP или метаданные HTML ).
В PHP вы можете использовать
default_charset
опцию php.ini или вручную выдатьContent-Type
заголовок MIME, который просто больше работает, но имеет тот же эффект.При кодировании вывода с использованием
json_encode()
добавьтеJSON_UNESCAPED_UNICODE
в качестве второго параметра.Вход :
К сожалению, вы должны проверить каждую полученную строку как действительную 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, вы делаете это безопасно. Это, к сожалению, самая сложная часть. Возможно, вы захотите широко использовать
mbstring
расширение PHP .Встроенные строковые операции PHP не являются безопасными по умолчанию в UTF-8. Есть некоторые вещи, которые вы можете безопасно делать с обычными строковыми операциями PHP (например, конкатенация), но для большинства вещей вы должны использовать эквивалентную
mbstring
функцию.Чтобы знать, что вы делаете (читай: не путайте), вам действительно нужно знать UTF-8 и как он работает на самом низком уровне. Проверьте любую из ссылок с utf8.com для некоторых хороших ресурсов, чтобы узнать все, что вам нужно знать.
источник
Я хотел бы добавить одну вещь к отличному ответу chazomaticus :
Также не забудьте мета-тег (например, или его HTML4 или XHTML-версию ):
Это кажется тривиальным, но IE7 доставлял мне проблемы с этим раньше.
Я все делал правильно; база данных, соединение с базой данных и HTTP-заголовок Content-Type были настроены на UTF-8, и он прекрасно работал во всех других браузерах, но Internet Explorer по-прежнему настаивал на использовании кодировки «западноевропейский».
Оказалось, что на странице отсутствовал тег META. Добавление, которое решило проблему.
Редактировать:
На самом деле W3C имеет довольно большой раздел, посвященный I18N . У них есть несколько статей, связанных с этой проблемой - описывающих стороны HTTP, (X) HTML и CSS:
Они рекомендуют использовать как заголовок HTTP, так и метатег HTML (или объявление XML, если XHTML используется в качестве XML).
источник
В дополнение к настройке
default_charset
в php.ini, вы можете отправлять правильную кодировку, используяheader()
код, перед любым выводом:Работать с Unicode в PHP легко, если вы понимаете, что большинство строковых функций не работают с Unicode, а некоторые могут полностью искажать строки . PHP считает "символы" длиной 1 байт. Иногда это нормально (например,
explode()
только ищет последовательность байтов и использует ее в качестве разделителя - поэтому не имеет значения, какие именно символы вы ищете). Но в других случаях, когда функция фактически предназначена для работы с символами , PHP не знает, что в вашем тексте есть многобайтовые символы, которые можно найти в Unicode.Хорошая библиотека для проверки - phputf8 . Это переписывает все «плохие» функции, чтобы вы могли безопасно работать со строками UTF8. Существуют такие расширения, как расширение mbstring, которые пытаются сделать это и для вас, но я предпочитаю использовать библиотеку, потому что она более переносима (но я пишу продукты для массового рынка, поэтому это важно для меня). Но phputf8 может использовать mbstring за кулисами, чтобы увеличить производительность.
источник
Я обнаружил проблему с кем-то, использующим PDO, и ответ состоял в том, чтобы использовать это для строки подключения PDO:
Сайт, с которого я взял это, не работает, но, к счастью, я смог получить его с помощью кеша Google.
источник
$dbh->exec("set names utf8");
; я предпочитаю метод, представленный здесь). Btw. на это есть также примечание в виде комментария в руководстве по PHP: php.net/manual/en/pdo.construct.php#96325 .В моем случае я использовал
mb_split
, который использует регулярные выражения. Поэтому я также должен был вручную убедиться, что кодировка регулярного выражения была utf-8, выполнивmb_regex_encoding('UTF-8');
Как примечание, я также обнаружил, запустив,
mb_internal_encoding()
что внутренняя кодировка не была utf-8, и я изменил это, запустивmb_internal_encoding("UTF-8");
.источник
Прежде всего, если вы находитесь в <5.3PHP, то нет. У вас есть куча проблем для решения.
Я удивлен, что никто не упомянул библиотеку intl , которая имеет хорошую поддержку юникода , графем , строковых операций , локализации и многих других, см. Ниже.
Я процитирую некоторую информацию о поддержке юникода в PHP на слайдах Элизабет Смит на PHPBenelux'14
INTL
Хорошо:
Плохой:
mb_string
Iconv
stream_filter_append($fp, 'convert.iconv.ISO-2022-JP/EUC-JP')
БАЗ
Некоторые другие Gotchas
Я обновлю этот ответ на случай, если что-то изменится, добавятся функции и так далее.
источник
--with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd
опциями.Единственное, что я хотел бы добавить к этим удивительным ответам, - это сделать акцент на сохранении ваших файлов в кодировке utf8. Я заметил, что браузеры принимают это свойство вместо установки utf8 в качестве кодировки кода. Любой приличный текстовый редактор покажет вам это, например, Notepad ++ имеет пункт меню для добавления файла, показывает текущую кодировку и позволяет вам ее изменить. Для всех моих php-файлов я использую utf8 без спецификации.
Некоторое время назад я попросил кого-то попросить меня добавить поддержку utf8 для приложения php / mysql, разработанного кем-то другим, я заметил, что все файлы были закодированы в ANSI, поэтому мне пришлось использовать ICONV для преобразования всех файлов, изменить таблицы базы данных, чтобы использовать utf8 charset и utf8_general_ci collate, добавьте «SET NAMES utf8» к уровню абстракции базы данных после соединения (если вы используете 5.3.6 или более раннюю версию, вы должны использовать charset = utf8 в строке соединения) и изменить строковые функции, чтобы использовать многобайтовый php строковые функции эквивалентны.
источник
Я недавно обнаружил, что с помощью
strtolower()
может вызвать проблемы, когда данные усекаются после специального символа.Решение было использовать
источник
Я только что прошел ту же самую проблему и нашел хорошее решение в руководствах PHP.
Я изменил кодировку всех файлов на UTF8, а затем кодировку по умолчанию для моего соединения. Это решило все проблемы.
Просмотреть исходный код
источник
set_charset('utf8mb4')
это не сработало, но сработало>set_charset("utf8")
, и это не было показано в других ответах.set_charset("utf8")
может работать, но будет вести себя по-другому (см. Замечания о разнице междуutf8
иutf8mb4
и историей версий mysql). Используйте,utf8
если вам нужно И ТОЛЬКО если вы знаете, что делаете !В PHP вам нужно либо использовать многобайтовые функции , либо включить mbstring.func_overload . Таким образом, такие вещи, как strlen, будут работать, если у вас есть символы, которые занимают более одного байта.
Вам также необходимо определить набор символов ваших ответов. Вы можете использовать AddDefaultCharset, как указано выше, или написать код PHP, который возвращает заголовок. (Или вы можете добавить мета-тег в ваши HTML-документы.)
источник
Поддержка Unicode в PHP по-прежнему огромная путаница. Хотя он способен конвертировать строку ISO8859 (которую он использует внутри) в utf8, ему не хватает возможности работать со строками Unicode изначально, что означает, что все функции обработки строк будут искажать и портить ваши строки. Таким образом, вы должны либо использовать отдельную библиотеку для правильной поддержки utf8, либо переписать все функции обработки строк самостоятельно.
Самая простая часть - просто указать кодировку в заголовках HTTP и в базе данных и тому подобное, но ничего из этого не имеет значения, если ваш код PHP не выводит допустимый UTF8. Это сложная часть, и PHP там практически не помогает. (Я думаю, что PHP6 должен исправить худшее из этого, но это еще далеко)
источник
Если вы хотите, чтобы сервер MySQL определял набор символов, а не PHP как клиент (старое поведение; на мой взгляд, предпочтительнее), попробуйте добавить его
skip-character-set-client-handshake
в разделmy.cnf
under[mysqld]
и перезапуститьmysql
.Это может вызвать проблемы в случае, если вы используете что-то кроме UTF8.
источник
Главный ответ отлично. Вот что мне нужно было сделать на обычной установке debian / php / mysql:
это все !
источник
Если вы хотите решение MySQL, у меня были аналогичные проблемы с 2 из моих проектов, после миграции сервера. После поиска и опробования множества решений я наткнулся на это / ничего до того, как это сработало):
После добавления этой строки в мой конфигурационный файл все работает отлично!
Я нашел это решение https://www.w3schools.com/PHP/func_mysqli_set_charset.asp, когда искал решение для вставки из запроса HTML
удачи!
источник
Просто примечание:
Вы столкнулись с проблемой ваших не латинских символов , показывая , как
?????????
вы задали вопрос, и он получил закрыт со ссылкой на этот канонический вопрос, вы перепробовали все , и независимо от того , что вы делаете , вы все еще получаете??????????
отMySQL
.Это в основном потому, что вы тестируете свои старые данные которые были вставлены в базу данных с использованием неправильной кодировки, а также преобразованы и сохранены в символы знака вопроса
?
. Это означает, что вы потеряли свой оригинальный текст навсегда, и независимо от того, что вы пытаетесь, вы получите???????
.Применение того, что вы узнали из ответов на этот вопрос на свежие данные, может решить вашу проблему.
источник
У меня была эта проблема при отображении таблиц. Я просто поместил это в каждую переменную вывода эха:
источник