Под моим контролем находится более двадцати сайтов на одном WEB-сервере. Большинство из них работают под управлением CMS Etomite версий от 0.6.1.2 до 1.1. Там везде используется кодировка windows-1251. Так уж сложилось, хорошо это или плохо.
Все эти сайты вначале разрабатывались на локальном сервере Denwer, инсталлировавшемся из комплекта Base_2006-10-04_a1.3.33_p4.4.3_m4.1.16_pma2.6.1.exe, включающего PHP4.
С Etomite и windows-1251 было всё замечательно. Но значительно позже (как жаль, что не раньше) добрые люди подсказали про MODx. Эта CMS (а вернее CMF) значительно лучше, но происходит от Etomite. При первых испытаниях MODx встал вопрос о кодировках. Переводить-то намечалось существующие сайты, со множеством материалов. И как-то боязно было всё конвертировать.
Это причина субъективная, практически неуважительная. Кроме того задумывался и о трафике. Всё-таки в UTF-8 при русскоязычном контенте трафик раза в полтора больше.
В общем, сначала я, как и многие другие, задумал перевести MODx в кодировку 1251. Сделать это вполне возможно путем настроек и изменения языковых файлов- останавливаться на этом не буду. Собственно, для самой системы управления достаточно выполнить штатные настройки языка в Инструменты-Конфигурация и в config.inc.php и всё будет работать. Но для дополнительных сниппетов и плагинов приходитсяиногда создавать дополнительные языковые файлы в кодировке 1251, а кое-где и влезать в код, чтобы заменить зашитую там кодировку utf-8.
В результате я получил вроде бы работающий сайт на MODx с кодировкой 1251. При этом не работали как надо некоторые сниппеты и плагины и их пришлось заменять на собственные или заимствованные из Etomite. Например AjaxSearch не хотел искать русские слова. Да и известная проблемас отображением некоторых русских символов оставалась.
Окончательный переход на MODx я отложил до выхода анонсированной версии MODx Revolution. Однако разработка Revolution застопорилась на alpha-версиях, а разработчики в конце 2008 года выпустили версию MODx 0.9.6.3. Вот на нее я и решил переехать и добиться полноценной работы.
На локальный сервер MODx 0.9.6.3. я поставил сразу в кодировке UTF-8. Поменяв в демонстрационном сайте часть страниц на русские я сразу убедился, что все известные ранее проблемы отпали.Тексты отображались правильно, превосходно работал AjaxSearch. Все-таки разработчики отлично потрудились, хотя и изменили всего лишь младший разряд в номере версии. Но возникли и проблемы.
Для тестирования сайтов в локальном режиме я использую комплект Denwer, где "всё в одном флаконе". Несколько лет я устанавливал Denwer из инсталляционного комплекта Base_2006-10-04_a1.3.33_p4.4.3_m4.1.16_pma2.6.1.exe, включающая PHP4.
Но эта версия оказалась непригодной для работы с MODx 0.9.6.3, так как в ней отстутствовало расширение для работы с мультибайтовыми строками. Это подтолкнуло к давно требовавшемуся решению - переходу на Denwer с PHP5. Поставил его из инсталляции Base_PHP5_2006-10-04_a1.3.33_p5.1.6_m4.1.16_pma2.6.1.exe с комплектом расширений Denwer3_PHP5_2008-01-13_5.2.4.exe. Старые базы данных и сайты просто перенес в новые каталоги.
Перевод на UTF-8 пока предусмотрен для одного сайта (как это сделано напишу ниже). Все остальные остались в кодировке 1251 и работают под Etomite.
В чем же причина? В конфигурационном файле my.cnf записано:
[client] port = 3306 socket = /tmp/mysql.sock default-character-set = cp1251 character-sets-dir = /usr/local/mysql4/share/charsets # # Параметры MySQL-сервера. # [mysqld] # Использовать режим совместимости с клиентами MySQL 3.x и MySQL 4.0. old-passwords # Кодировка баз данных по умолчанию. default-character-set = cp1251 init-connect = "set names cp1251"
Всё вроде бы правильно. В свойствах и баз данных, и таблиц везде указана кодировка cp1251, данные в таблицах просматриваются программой MySQLFront, а вот в браузер выдаются неправильно.
В head страниц прописано
<meta http-equiv="content-type" content="text/html; charset=Windows-1251" />
В таких условиях страницы, возвращаемые MODx, как при кодировке 1251, так и при UTF-8 выглядят нормально, а вот для Etomite - неправильные.
Что в таких условиях можно предпринять для нормальной работы?
Конфигурация WEB-сервера Apache одинаковая, за исключением загрузки разных версий PHP. Конфигурация MySQL в my.conf абсолютно одинаковая. Базы данных имеют правильные опции и кодировки. Версии mysql абсолютно одинаковые. Следовательно - проблема кроется в работе PHP5 с базами данных.
В PHP.INI заремлены
;default_charset = "iso-8859-1"
и одинаковая конфигурация для MySQL.
В конфигурации MODx в config.inc.php записаны дополнительные настройки, отсутствующие в ETOMITE:
$database_connection_charset = 'utf8'; $database_connection_method = 'SET NAMES';
При обращении к БД выполняются запросы
mysql_select_db(str_replace('`', '', $dbase));
@mysql_query("{$database_connection_method} {$database_connection_charset}");
Второй дополнительный запрос выполняется каждый раз после mysql_select_db. А вот в Etomite подобного нет! Это и является причиной ошибок. Однако для исправления необходимо влезать в код Etomite. Для локального сервера это сделать достаточно просто, но как это выполнить на хостинге, где имеется куча сайтов с разными версиями движка?
Такие проблемы имеют несколько причин и путей решения. Основная в данном случае - PHP использует неверную кодировку в качестве клиентской. В базе данных кодировка правильная, а клиенту возвращаются вопросы. Решить её можно так:
Решение 1. Сделать, как в MODx - отправкой запроса SET NAMES. Но этого хотелось бы избежать - слишком много кода на разных сайтах придется изменять.
Решение 2. Заставить MySQL автоматом выполнять этот запрос при каждом коннекте к нему.
Для этого нужно в файле my.cnf иметь строку:
init-connect="SET NAMES cp1251"
Такая строка уже есть, но в секции [mysqld], а советуют про [server]. Попробовал сделать - не помогло.
Причина совсем не в секции [server], а в том, что на локальном сервере, для простоты, подключение выполняется от имени пользователя root. Этот пользователь обладает всеми правами и на него этот прием не действует. Но на хостинге нам никто не даст соединяться как root, там всегда для клиентов имеются специальные пользователи.
Пришлось создать дополнительного пользователя с ограниченными правами и на локальном сервере. Записали этого пользователя и его пароль в config.inc.php для всех сайтов, работающих под управлением Etomite и - ура, заработало!
При этом правильно работают и сайты под MODx. Сайты с Etomite не посылают запрос SET NAMES cp1251, но получают данные именно в этой кодировке автоматически, так как она задана в init-connect="SET NAMES cp1251".
А сайты с MODx сами отправляют запросы SET NAMES utf8 и для них данные возвращаютс в этой кодировке.
Это пока маленькие беды, так как речь идет о локальном сервере, работающем под Windows. Что будет при переезде на хостинг - совсем другая история.
Написать комментарий