пʼятниця, 21 грудня 2007 р.

Кодування MySQL і PHP: досвід міграції старого сайту та важливі уточнення

Після переходу з MySQL 4 на MySQL 5 я зіткнувся з некоректним відображенням кирилиці у старому PHP-сайті. У 2007 році цей сайт працював із Windows-1251, тому важливо було простежити кодування на всьому шляху: від бази даних до браузера.

Три різні рівні кодування

Потрібно узгодити фактичне кодування даних у базі, кодування з’єднання клієнта із сервером і кодування HTTP-відповіді. Сам перехід на MySQL 5 не означав, що всі бази автоматично ставали UTF-8: параметри задаються на різних рівнях сервера, бази, таблиці й стовпця.

SET NAMES 'cp1251' за документацією MySQL повідомляє серверу, в якому кодуванні клієнт надсилає запити та очікує результати. Команда не є універсальним перетворювачем неправильно збережених даних. Значення слід обирати відповідно до реального кодування застосунку.

Приклади з початкового допису

У phpNuke я додавав запит після підключення до бази у файлі mainfile.php. Також вказував кодування на початку дампа під час перенесення між серверами. У тодішній конфігурації Apache2 використовував файл /etc/apache2/conf.d/charset; розташування конфігурації в інших інсталяціях може відрізнятися.

Код нижче збережено як історичний матеріал. У ньому є помилки й застарілий синтаксис, тож це не готовий сценарій міграції:

// Rudjuk 24.06.2007 Change Error Code
if ($db){
  $db->sql_query("set names 'cp1251'");
}

SET NAMES CP1251

< meta http-equiv="content-type" content="text/html; charset=windows-1251" />

AddDefaultCharset windows-1251

SHOW VARIABLES LIKE 'character_set_client';

CREATE DATABASE `inv2_neru`  CHARACTER SET cp1251 COLLATE cp1251_bin COLLATE cp1251_bin;
^
CREATE TABLE `ibf_admin_login_logs` (
  `admin_id` int(10) NOT NULL auto_increment,
  `admin_ip_address` varchar(16) NOT NULL default '0.0.0.0',
  `admin_username` varchar(40) NOT NULL default '',
  `admin_time` int(10) unsigned NOT NULL default '0',
  `admin_success` int(1) unsigned NOT NULL default '0',
  `admin_post_details` text,
  PRIMARY KEY  (`admin_id`),
  KEY `admin_ip_address` (`admin_ip_address`),
  KEY `admin_time` (`admin_time`)
) TYPE=MyISAM AUTO_INCREMENT=84    CHARACTER SET cp1251 COLLATE cp1251_bin;
^

Що потрібно виправити перед використанням

  • У рядку CREATE DATABASE двічі повторено COLLATE; має бути одна відповідна умова.
  • Запис < meta містить зайвий пробіл після кутової дужки.
  • Роздільники ^ не є самостійними SQL-командами.
  • Старий приклад із TYPE=MyISAM треба перевіряти за синтаксисом цільової версії; механічно переносити весь DDL не можна.

Директива Apache AddDefaultCharset задає параметр charset для відповідей text/plain і text/html. Вона не перекодовує самі байти; за документацією Apache її слід застосовувати лише до ресурсів із відомим однаковим кодуванням. Глобальна заміна на Windows-1251 може зіпсувати відображення інших сторінок.

Перед міграцією збережіть копію бази та перевірте шлях даних на тестовому середовищі. У MySQL 8.0 підтримується utf8mb4, але перехід до нього потребує коректного перетворення фактичних даних і налаштування клієнта.

Немає коментарів:

Партнерська програма K2 ERP: п’ять рівнів від рекомендацій до власних продуктів

Перша рекомендація клієнту може стати початком власного напряму бізнесу з K2 ERP. Оновлена партнерська програма поєднує самостійну реєстрац...