UTF-8 полностью

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

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

Это для нового сервера Linux, на котором работают MySQL 5, PHP, 5 и Apache 2.

Вот обзор всех возможных ошибок кодирования: sebastianviereck.de/en/…

Sebastian Viereck 27.01.2013 14:29

Вот введение в кодировки в целом и кодировки в PHP в частности: Что абсолютно необходимо знать каждому программисту о кодировках и наборах символов для работы с текстом

deceze 09.07.2013 23:33

Некоторые недавние обсуждение PHP 7 указывают на то, что нет никаких изменений в позиции "официально заброшенной" в 2010 году ... Есть что-нибудь еще о "PHP7 и UTF-8"?

Peter Krauss 23.09.2015 09:02

Это обычная проблема. Но быстрого решения нет, вам придется настроить utf-8 для каждого из них отдельно - MySQL 5, PHP5 ИЛИ Apache2.

Manish Shrivastava 18.01.2017 17:00
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1 238
4
168 749
15

Ответы 15

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

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

Отличный совет о настройке func_overload - позволяет минимизировать модификацию существующего кода.

Simon East 15.01.2014 08:56

Просто будьте осторожны - некоторый код может фактически полагаться на однобайтовую природу стандартных строковых функций.

JW. 15.01.2014 22:18

Важно отметить, что функция mbstring.func_overload устарела с PHP 7.2 из-за проблем, отмеченных в комментарии @ JW выше. Итак, лучший совет: да, вам обязательно следует использовать функции mbstring, но не используйте функцию перегрузки, чтобы стандартные функции работали как многобайтовые.

Simba 07.02.2017 16:08

В дополнение к настройке 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.

Marten Koetsier 13.08.2015 16:55

См. Также Ответ Палека на PDO + MySQL и сломанная кодировка UTF-8.

Peter Mortensen 08.07.2019 19:21

Вы спасли мою жизнь.

Roberto Sepúlveda Bravo 14.08.2020 19:03

Недавно я обнаружил, что использование 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

INTL

Хорошо:

  • Обертка вокруг библиотеки ICU
  • Стандартизированные языковые стандарты, установка языковых стандартов для каждого скрипта
  • Форматирование чисел
  • Форматирование валюты
  • Форматирование сообщения (заменяет gettext)
  • Календари, даты, часовой пояс и время
  • Транслитератор
  • Spoofchecker
  • Пакеты ресурсов
  • Конверторы
  • Поддержка IDN
  • Графемы
  • Сопоставление
  • Итераторы

Плохой:

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

mb_string

  • Включает поддержку zend_multibyte
  • Поддерживает прозрачное кодирование ввода / вывода HTTP
  • Предоставляет некоторые оболочки для таких функций, как strtoupper

ICONV

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

БАЗЫ ДАННЫХ

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

Некоторые другие проблемы

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

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

Да, верно. Mysqli и PDO могут использовать свои собственные драйверы. Также они могут использовать драйвер mysqlnd, если вы будете компилировать php с опциями --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd.

Alexander Yancharuk 16.02.2014 21:54

Единственное, что я бы добавил к этим удивительным ответам, - это подчеркнуть сохранение ваших файлов в кодировке 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") работал, и это фактически не было показано в других ответах.

Funk Forty Niner 21.01.2017 17:16

@FunkFortyNiner Остерегайтесь: set_charset("utf8") может работать, но будет вести себя по-другому (см. Примечания о разнице между utf8 и utf8mb4 и историю версий mysql). Используйте utf8если тебе нужно И ТОЛЬКО если ты знаешь что делаешь!

Martin Hennings 24.04.2018 13:09

Решение 5 звезд, я читал текстовый файл построчно и получал? для каждого символа я сделал save-as вместо ansi использовал utf8. благодаря.

Atef Farouk 12.01.2020 09:22

Если вам нужно решение 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

Другие вопросы по теме