В UTF-8 Все путем




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



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



Это для нового сервера Linux , запуск MySQL 5, PHP 5 и Apache 2.

624   13  

13 ответов:

Хранилище Данных:

  • указать utf8 кодировка всех таблиц и текстовых столбцов в базе данных. Это делает MySQL физически хранить и извлекать значения, закодированные изначально в UTF-8. Обратите внимание, что MySQL будет неявно использовать utf8 кодировка, если a utf8_* параметры сортировки задаются (без явного набора символов).

  • в старых версиях MySQL (utf8, который поддерживает только подмножество символов Unicode. Жаль, что я не шучу.

Доступ К Данным:

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

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

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

      $dbh = new PDO('mysql:charset=utf8');
      
    • если вы используете mysqli, вы можете позвонить set_charset():

      $mysqli->set_charset('utf8');       // object oriented style
      mysqli_set_charset($link, 'utf8');  // procedural style
      
    • если вы застряли с простым mysql но, оказывается, работает PHP ≥ 5.2.3, вы можете позвонить mysql_set_charset.

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

  • то же самое соображение относительно utf8/utf8 применяется, как указано выше.

выход:

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

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

Input:

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

  • из моего чтения текущих HTML spec, следующие под-пули не нужны или даже действительны больше для современного HTML. Я понимаю, что браузеры будут работать и отправлять данные в наборе символов, указанном для документ. Однако, если вы ориентируетесь на более старые версии HTML (XHTML, HTML4 и т. д.), эти пункты все еще могут быть полезны:

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

Другие Соображения, Код:

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

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

Я хотел бы добавить одну вещь к chazomaticus' отличный ответ:

Не забудьте метатег либо (как это, или HTML4 или XHTML версия его):

<meta charset="utf-8">

это кажется тривиальным, но IE7 дал мне проблемы с этим раньше.

Я все делал правильно; база данных, подключение к базе данных и HTTP-заголовок Content-Type были установлены на UTF-8, и он отлично работал во всех других браузерах, но Internet Explorer по-прежнему настаивал на использовании "западноевропейской" кодировки.

оказалось, что на странице отсутствует метатег. Добавление этого решило проблему.

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');

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

хорошая библиотека, чтобы проверить в это 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, к счастью.

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

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

прежде всего, если вы находитесь в

Я удивлен, что никто не упомянул международный библиотека, которая имеет хорошую поддержку unicode,графемы,строковые операции,локализация и многое другое, см. ниже.

Я приведу некоторые сведения о поддержке unicode в PHP от Элизабет Смит горки at PHPBenelux ' 14

международный

хорошо:

  • обертка вокруг библиотеки ICU
  • стандартизированные локали, установите локаль для каждого скрипта
  • форматирование
  • валюты
  • форматирование сообщений (заменяет gettext)
  • календари, даты, часовой пояс и время
  • Транслитератор
  • Spoofchecker
  • пакеты ресурсов
  • шт.
  • поддержка IDN
  • графемы
  • сортировка
  • итераторы

плохое:

  • не поддерживает zend_multibite
  • не поддерживает преобразование ввода-вывода HTTP
  • не поддерживает функцию перегрузка

mb_string

  • включает поддержку zend_multibyte
  • поддерживает прозрачную кодировку HTTP in / out
  • предоставляет некоторые обертки для funtionallity, такие как strtoupper

ICONV

  • основной для преобразования кодировки
  • обработчик выходного буфера
  • кодировка mime функциональность
  • преобразование
  • некоторые строки помощников (len, substr, strpos, strrpos)
  • Stream Filter stream_filter_append($fp, 'convert.iconv.ISO-2022-JP/EUC-JP')

базы данных

  • mysql: кодировка и параметры сортировки в таблицах и при подключении (не параметры сортировки). Также не используйте mysql-msqli или PDO
  • postgresql: pg_set_client_encoding
  • sqlite( 3): убедитесь, что он был скомпилирован с unicode и intl поддержка

некоторые другие Gotchas

  • вы не можете использовать имена файлов unicode с PHP и windows, Если вы не используете расширение 3-й части.
  • отправить все в ASCII, если вы используете exec, proc_open и другие вызовы командной строки
  • обычный текст не является обычным текстом, файлы имеют кодировки
  • вы можете конвертировать файлы на лету с помощью фильтра с iconv

Я буду обновлять этот ответ в случае, если вещи меняют добавленные функции и так далее.

Я недавно обнаружил, что с помощью strtolower() может вызвать проблемы, когда данные усекаются после специального символа.

решение было использовать

mb_strtolower($string, 'UTF-8');

mb_ использует многобайтовые. Он поддерживает больше символов, но в целом немного медленнее.

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

некоторое время назад у меня кто-то попросил меня добавить поддержку utf8 для a на PHP/MySQL приложения, разработанные кем-то еще, я заметил, что все файлы были в кодировке ANSI, так что мне пришлось использовать функцию iconv для преобразования всех файлов, изменение таблиц базы данных для использования в utf8 и utf8_general_ci разобрать, добавить в комплект именами в формате utf8', чтобы слой абстракции данных после подключения (если используется 5.3.6 или раньше, в противном случае вам придется использовать кодировка=utf8 в строку подключения) и изменить строковые функции использовать PHP многобайтовые строковые функции эквивалентны.

в PHP вам нужно будет либо использовать многобайтовые функции или mbstring.func_overload. Таким образом, такие вещи, как strlen, будут работать, если у вас есть символы, которые занимают более одного байта.

вам также необходимо определить набор символов ваших ответов. Вы можете либо использовать AddDefaultCharset, как указано выше, либо написать PHP-код, который возвращает заголовок. (Или вы можете добавить метатег в свои HTML-документы.)

Я только что прошел через ту же проблему и нашел хорошее решение в руководствах 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());
}

Посмотреть Источник

поддержка Unicode в PHP по-прежнему является огромным беспорядком. Хотя он способен преобразовывать строку ISO8859 (которую он использует внутри) в utf8, ему не хватает возможности работать со строками unicode изначально, что означает, что все функции обработки строк будут искажать и повреждать ваши строки. Поэтому вам нужно либо использовать отдельную библиотеку для правильной поддержки utf8, либо переписать все функции обработки строк самостоятельно.

легкая часть просто указывает кодировку в заголовках HTTP и в базе данных и тому подобное, но ничто из этого не имеет значения, если ваш PHP-код не выводит допустимый UTF8. Это самая сложная часть, и PHP практически не помогает вам. (Я думаю, что PHP6 должен исправить худшее из этого, но это еще не скоро)

верхний ответ отличный. Вот что мне пришлось сделать при обычной настройке 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

все !

если вы хотите, чтобы сервер MySQL определял набор символов, а не PHP в качестве клиента (старое поведение; предпочтительно, на мой взгляд), попробуйте добавить skip-character-set-client-handshake на my.cnf, под [mysqld] и перезапустите mysql.

это может вызвать проблемы в случае, если вы используете что-либо, кроме UTF8.

Comments

    Ничего не найдено.