php value default charset windows 1251
Определение кодировки текста в PHP — обзор существующих решений плюс еще один велосипед
Столкнулся с задачей — автоопределение кодировки страницы/текста/чего угодно. Задача не нова, и велосипедов понапридумано уже много. В статье небольшой обзор найденного в сети — плюс предложение своего, как мне кажется, достойного решения.
Если кратко — он не работает.
Давайте смотреть:
Как видим, на выходе — полная каша. Что мы делаем, когда непонятно почему так себя ведет функция? Правильно, гуглим. Нашел замечательный ответ.
Чтобы окончательно развеять все надежды на использование mb_detect_encoding(), надо залезть в исходники расширения mbstring. Итак, закатали рукава, поехали:
Постить полный текст метода не буду, чтобы не засорять статью лишними исходниками. Кому это интересно посмотрят сами. Нас истересует строка под номером 593, где собственно и происходит проверка того, подходит ли символ под кодировку:
Вот основные фильтры для однобайтовой кириллицы:
Windows-1251 (оригинальные комментарии сохранены)
ISO-8859-5 (тут вообще все весело)
Как видим, ISO-8859-5 всегда возвращает TRUE (чтобы вернуть FALSE, нужно выставить filter->flag = 1).
Когда посмотрели фильтры, все встало на свои места. CP1251 от KOI8-R не отличить никак. ISO-8859-5 вообще если есть в списке кодировок — будет всегда детектиться как верная.
В общем, fail. Оно и понятно — только по кодам символов нельзя в общем случае узнать кодировку, так как эти коды пересекаются в разных кодировках.
2. Что выдает гугл
А гугл выдает всякие убожества. Даже не буду постить сюда исходники, сами посмотрите, если захотите (уберите пробел после http://, не знаю я как показать текст не ссылкой):
http:// deer.org.ua/2009/10/06/1/
http:// php.su/forum/topic.php?forum=1&topic=1346
3. Поиск по хабру
2) на мой взгляд, очень интересное решение: habrahabr.ru/blogs/php/27378/#comment_1399654
Минусы и плюсы в комменте по ссылке. Лично я считаю, что только для детекта кодировки это решение избыточно — слишком мощно получается. Определение кодировки в нем — как побочный эффект ).
4. Собственно, мое решение
Идея возникла во время просмотра второй ссылки из прошлого раздела. Идея следующая: берем большой русский текст, замеряем частоты разных букв, по этим частотам детектим кодировку. Забегая вперед, сразу скажу — будут проблемы с большими и маленькими буквами. Поэтому выкладываю примеры частот букв (назовем это — «спектр») как с учетом регистра, так и без (во втором случае к маленькой букве добавлял еще большую с такой же частотой, а большие все удалял). В этих «спектрах» вырезаны все буквы, имеющие частоты меньше 0,001 и пробел. Вот, что у меня получилось после обработки «Войны и Мира»:
Спектры в разных кодировках (ключи массива — коды соответствующих символов в соответствующей кодировке):
Далее. Берем текст неизвестной кодировки, для каждой проверяемой кодировки находим частоту текущего символа и прибавляем к «рейтингу» этой кодировки. Кодировка с бОльшим рейтингом и есть, скорее всего, кодировка текста.
Результаты
У-упс! Полная каша. А потому что большие буквы в CP1251 обычно соответствуют маленьким в KOI8-R. А маленькие буквы используются в свою очередь намного чаще, чем большие. Вот и определяем строку капсом в CP1251 как KOI8-R.
Пробуем делать без учета регистра («спектры» case insensitive)
Как видим, верная кодировка стабильно лидирует и с регистрозависимыми «спектрами» (если строка содержит небольшое количество заглавных букв), и с регистронезависимыми. Во втором случае, с регистронезависимыми, лидирует не так уверенно, конечно, но вполне стабильно даже на маленьких строках. Можно поиграться еще с весами букв — сделать их нелинейными относительно частоты, например.
5. Заключение
В топике не расмотрена работа с UTF-8 — тут никакий принципиальной разницы нету, разве что получение кодов символов и разбиение строки на символы будет несколько длиннее/сложнее.
Эти идеи можно распространить не только на кириллические кодировки, конечно — вопрос только в «спектрах» соответствующих языков/кодировок.
P.S. Если будет очень нужно/интересно — потом выложу второй частью полностью работающую библиотеку на GitHub. Хотя я считаю, что данных в посте вполне достаточно для быстрого написания такой библиотеки и самому под свои нужды — «спектр» для русского языка выложен, его можно без труда перенести на все нужные кодировки.
UPDATED
В комментариях проскочила замечательная функция, ссылку на которую я опубликовал под графом «убожество». Может быть погорячился со словами, но уж как опубликовал, так опубликовал — редактировать такие вещи не привык. Чтобы не быть голословным, давайте разберемся, работает ли она на 100%, как об этом говорит предполагаемый автор.
1) будут ли ошибки при «нормальной» работе этой функции? Предположим, что контент у нас на 100% валидный.
ответ: да, будут.
2) определит ли она что-нибудь кроме UTF-8 и не-UTF-8?
ответ: нет, не определит.
Настройка параметров PHP
По умолчанию на новых серверах PHP работает в режиме mod_php, но при желании вы можете подключить режим mod_cgi, воспользовавшись нашей инструкцией.
apc.cache_by_default
Управление APC осуществляется директивами:
default_charset
Директива указывает кодировку по умолчанию (например, cp1251, utf-8, koi8-r) для всех выдаваемых страниц.
display_errors
Директива указывает, требуется ли выводить ошибки на экран вместе с остальным выводом, либо ошибки должны быть скрыты от пользователя.
Включение и выключение осуществляются следующим образом:
log_errors
Опция позволяет включить логирование ошибок php с их записью в произвольный файл (в примере errors.log). При указании пути к файлу замените u и user на первую букву вашего логина и сам логин.
magic_quotes_gpc
Включение и выключение magic_quotes осуществляется директивами:
mail.add_x_header
Опция позволяет включить логирование отправки почты из скриптов сайта. Логи будут содержать полный путь до скрипта, адрес получателя и заголовки. При указании пути к файлу, в который будут записываться логи (mail.log), замените u и user на первую букву вашего логина и сам логин.
max_input_vars
Директива указывает, сколько входных переменных может быть принято в одном запросе. Например:
mbstring.func_overload и mbstring.internal_encoding
Для корректной работы сайтов на старых версиях CMS Битрикс (до v20.100.0) требуются следующие параметры:
opcache.revalidate_freq
Отключение OpCache (настройка требуется для CMS Битрикс):
pcre.recursion_limit
Устанавливает лимит на рекурсию.
post_max_size
register_globals
Директивы для включения/выключения глобальных переменных:
request_order
Директива регулирует порядок, в котором PHP добавляет переменные GET, POST и Cookie в массив _REQUEST.
upload_max_filesize
Устанавливает максимальный размер закачиваемого файла.
Настройка опций в файле php.ini
allow_url_fopen
Опция включает поддержку оберток URL (URL wrappers), которые позволяют работать с объектами URL по протоколам ftp или http как с обычными файлами.
Включение опции (для отключения значение = 0):
apc.cache_by_default
Отключение APC (для включения значение = 1):
default_charset
Указание кодировки по умолчанию:
display_errors
Включение вывода ошибок (для выключения значение = off).
magic_quotes_gpc
Отключение Magic Quotes (для включения значение = 1):
mail.add_x_header
Включение логирования отправки почты из скриптов сайта. В директиве mail.log указывается путь к файлу, в который будут сохраняться логи (замените u и user на первую букву вашего логина и сам логин).
max_input_vars
Изменение количества вводимых переменных:
mbstring.func_overload и mbstring.internal_encoding
Настройки для старых версий CMS Битрикс:
opcache.revalidate_freq
Отключение OpCache (настройка для CMS Битрикс):
pcre.recursion_limit
post_max_size
register_globals
Отключение Register Globals (для включения значение = 1):
request_order
Регулирует порядок, в котором PHP добавляет переменные GET, POST и Cookie в массив _REQUEST.
upload_max_filesize
Устанавливает максимальный размер закачиваемого файла.
Опции, которые не могут быть изменены
К настройкам PHP, изменение которых невозможно в рамках виртуального хостинга, относятся:
Решение проблем неправильной кодировкой веб-страницы
При неправильной кодировке весь сайт или его часть отображаются в виде «кряпозяблов», т.е. непонятных символов, делающих текст нечитаемым. Такая ситуация может возникнуть при неверной настройке кодировки веб-сервера или при отсутствии настроек. Рассмотрим возможные варианты и способы устранения проблем
Неправильная кодировка HTML страниц
Создадим тестовый файлик:
Скопируем в него следующий HTML код, в котором отсутствует указание кодировки и посмотрим, какие проблемы могут с ним возникнуть и как их решить:
Как можно видеть, кодировка браузером определена неправильно:
Имеется несколько способов исправить эту ситуацию. Начнём с самого простого – явно указать кодировку для веб-страницы. Это делается метатегом, который должен быть расположен внутри тэга head:
Добавим эту строку к нашему тестовому файлику, чтобы получилось так:
Как мы можем убедиться на следующем скриншоте, проблема решена:
Если кодировка вашего файла отличается от UTF-8, то вместо неё поставьте windows-1251 или ту, которая соответствует кодировке веб-страницы. Чтобы научиться определять кодировку файлов, посмотрите эту инструкцию.
Это был самый простой способ исправления проблемы с кодировкой – без изменения настроек сервера.
Вернём наш тестовый файл в исходное состояние и продолжим изучение способов указания кодировки.
Если файлы .htaccess включены настройками Apache, то эти файлы можно использовать чтобы указывать кодировку отправляемых веб-сервером страниц. Чтобы включить поддержку файлов .htaccess в конфигурационном файле Apache ( /etc/apache2/apache2.conf ) найдите группу строк
После этого сервер нужно перезапустить.
Файл .htaccess должен быть размещён в той же директории, что и сайт. Мой сайт размещён в корневой директории веб-сервера. Если у вас также, то теперь в папке /var/www/html/ создайте файл .htaccess и добавьте в него директиву AddDefaultCharset после которой укажите желаемую кодировку. Примеры
Можно указать кодировку, которая будет применена только к файлам определённого формата:
Набор файлов может быть любым, например:
Следующий вариант является альтернативным и также позволяет устанавливать кодировку для файлов определённого типа, для него нужно, чтобы был включён mod_headers:
Ещё один вариант, который также можно использовать в файле .htaccess для установки кодировки UTF-8:
Если сайт на PHP, то дополнительно может понадобиться продублировать кодировку с php_value default_charset:
Как установить UTF-8 кодировку в PHP
В PHP скрипте для установки кодировки используется header, например:
Обычно вместе с кодировкой также указывают тип содержимого (в примере вариант для HTML страницы):
Ещё один вариант для RSS ленты:
Помните, что функция header должна быть вызвана перед любым выводом в браузер. В противном случае (если вывод в браузер уже был сделан), то уже были отправлены и заголовки. Очевидно, что в этом случае их уже невозможно поменять. Если в браузер было выведено сообщение об ошибке, то заголовки также уже были отправлены и использование header вызовет ошибку. Для проверки, были ли уже отправлены заголовки, используйте headers_sent.
Описанный способ работает только когда PHP скрипт полностью генерирует содержимое страницы. Статические страницы (такие как html) вы должны сохранять в кодировке utf-8. Большинство веб серверов обратят внимание на кодировку файла и добавят соответствующий заголовок. На самом деле, сохранение PHP файла в кодировке utf-8 приведёт к такому же результату.
Неправильная кодировка результатов из базы данных MySQL
Если ваш сайт состоит из статической части (шаблон) и динамической, которая формируется из данных, получаемых из базы данных, то может возникнуть ситуация, когда часть сайта имеет правильную кодировку, а другая часть сайта имеет неправильную. В этом случае бесполезно менять настройки веб-сервера – поскольку всё равно часть страницы будет иметь неправильную кодировку.
Нужно начать с определения кодировки ваших таблиц. Можно посмотреть в phpMyAdmin:
Обратите внимание на столбец «Сравнение», запись «utf8_unicode_ci» означает, что используется кодировка UTF-8.
Можно подключиться к СУБД MySQL и проверить кодировку таблиц без phpMyAdmin. Для этого:
Если вы забыли имя базы данных, то выполните команду:
Предположим, я хочу посмотреть кодировку для таблиц в базе данных information_schema
Если вы забыли имя таблиц, выполните:
Далее выполните команду, в которой имя_таблицы замените на настоящее имя таблицы:
Вы увидите примерно следующее:
Смотрите столбец Collation. В моём случае там utf8_general_ci, это, как и utf8_unicode_ci, кодировка UTF-8. Кстати, если вы не знаете в чём разница между кодировками utf8_general_ci, utf8_unicode_ci, utf8mb4_general_ci, utf8mb4_unicode_ci, а также какую кодировку выбрать для базы данных MySQL, то посмотрите эту статью.
Теперь, когда мы узнали кодировку (в моём случае это UTF-8), то при каждом подключении к СУБД MySQL нужно выполнять последовательно запросы:
В PHP это можно сделать примерно так:
Обратите внимание, что UTF8 вам нужно заменить на ту кодировку, которая используется для ваших таблиц.
Изменение кодировки файлов
Если вы решили пойти другим путём и вместо установки новой кодировки изменить кодировку ваших файлов, то посмотрите статью «Как конвертировать файлы в кодировку UTF-8 в Linux». В ней рассказано, как узнать текущую кодировку файлов и как конвертировать файлы в любую кодировку (не только UTF-8).
Как узнать, какую кодировку отправляет сервер
Если вы хотите узнать, какие настройки кодировки имеет веб-сервер (какую кодировку передаёт в заголовках), то воспользуйтесь следующей командой:
В ней вместо URL вставьте реальный адрес проверяемого сайта. Если сайт использует HTTPS, то укажите адрес сайта вместе с протоколом, например
Какую кодировку выбрать для веб-сайта
Рекомендуется выбрать кодировку UTF-8. Это более универсальная кодировка, практически, она стала стандартом. У вас не будет проблем с отображением необычных символов и букв из других алфавитов.
Директива Default_charset
Директива Default_charset указывает кодировку по умолчанию для всех PHP документов. Наиболее часто используються следующие кодировки символов: UTF-8, ASCII, Windows-1251 (CP1251).
Пример использования:
В зависимости от версии интерпретатора PHP, директива Default_charset имеет разные значения по умолчанию, поэтому не рекомендуется оставлять параметр директивы пустым.
Начиная с версии PHP 5.6 значение по умолчанию является UTF-8 и используется для большинства функций, в частности и для функций Mbstring, если кодировка не изменена в параметрах вызова данных функций. Если директива Default_charset имеет пустой параметр, то кодировка PHP документов определяется директивами AddDefaultCharset, AddCharset в файле .htaccess.
Кодировка, указанная в директиве Default_charset используется для стандартного заголовка Content-Type, отправляемого PHP, если этот заголовок не переопределен вызовом функции Header.
Проверить статус директивы можно с помощью функции Ini_get:
Директива Default_charset относиться к режиму PHP_INI_ALL, поэтому значение может быть установлено отовсюду (более детально в статье: Установка параметров конфигурации PHP).
Кодировку можно также изменить непосредственно в исполняемом файле PHP с помощью функции Ini_set:
или в настройках файла .htaccess:
Будьте внимательны при написании параметра директивы, поскольку системных ошибок не будет, а вывод информации испортиться:
Установлен устаревший параметр PHP mbstring.internal_encoding и его значение конфликтует
Обновили модуль обновления, появилось сообщение
Цитата |
---|
Установлен устаревший параметр PHP mbstring.internal_encoding и его значение конфликтует со значением параметра default_charset. Пожалуйста, исправьте значения указанных параметров или обратитесь в службу технической поддержки вашего хостинга.. |
Ответ от техподдержки: Параметры mbstring.internal_encoding, default_charset в конфигурации PHP и кодировка сайта должны быть одинаковыми
Сайт на windows-1251
Подскажите, пожалуйста, как поправить? в каких файла?
P.S. После правок в /etc перезагружай http
Может что-то еще забыл?
Цитата |
---|
Вячеслав Любовин написал: Параметры mbstring.internal_encoding, default_charset в конфигурации PHP и кодировка сайта должны быть одинаковыми |
интересно а как быть в ситуации когда на серваке есть сайты и utf 8 и 1251 кодировки
default_charset для всех один ведь и получается сайты надо переводить с 1251 на utf-8
Доброго всем дня. Давайте по порядку)
Вячеслав Любовин, ваш сайт на windows-1251 кодировке когда был создан на какой версии машины? (важно, потому что были доработки, не факт что у вас они есть, потому уточняю).
Вообще менять тут как минимум неверно) Это общие параметры всей машины. По умолчанию там должно быть:
Если посмотрите конфиг файлы httpd для UTF-8 сайтов, то там этих строк не будет. Эти опции будут браться из файла /etc/php.d/bitrixenv.ini.
Кроме того чтобы система обновлений проекта работала после обновления для проекта в кодировке windows-1251 нужно для этого проекта в файле /bitrix/php_interface/dbconn.php добавить строку:
Это подправим в следующей бете 7.4.12.
Цитата |
---|
Александр Панишев написал: интересно а как быть в ситуации когда на серваке есть сайты и utf 8 и 1251 |
кодировки default_charset для всех один ведь и получается сайты надо переводить с 1251 на utf-8
Алексей Шафранский, Устанавливал на свежую 7.4.3
После загрузки машины, был удален дефолтный сайт, и создан на windows 1251, потом бэкап был перенес с хостинга
Далее всеми правдами и не правдами пытался избавиться от ошибок которые возникали при проверке битрикса