Як виглядає проблема
До
INSERT INTO wp_posts (post_title) VALUES ('Замовлення готове — доставка РІ середу');Після
INSERT INTO wp_posts (post_title) VALUES ('Замовлення готове — доставка в середу');Звідки це береться
WordPress зберігає текст в UTF-8. Але багато старих установок створювали таблиці в latin1 або cp1251 чи підключалися до бази з таким кодуванням. Поки запис і читання роблять одну й ту саму помилку, ніхто нічого не помічає. Після перенесення на новий сервер, експорту через phpMyAdmin або зміни кодування з’єднання кожна українська літера раптом перетворюється на два символи.
DB_CHARSETуwp-config.phpдорівнюєlatin1або не збігається з таблицями.- Дамп експортували як
latin1, а імпортували якutf8mb4— або навпаки. - Плагін чи скрипт імпорту ще раз перекодував уже зіпсований текст. Так виникає подвійне кодування.
Виправляємо експорт
- Зробіть резервну копію бази, перш ніж щось змінювати.
- Експортуйте потрібні таблиці у файл
.sql, наприклад через phpMyAdmin абоmysqldump --default-character-set=utf8mb4. - Перетягніть файл у поле вище. Mojibuster виправить лише зіпсовані місця й покаже кожну зміну.
- Завантажте виправлений файл та імпортуйте його в чисту тестову базу з кодуванням
utf8mb4. - Перевірте сайт. Якщо все гаразд, імпортуйте файл у робочу базу.
Дамп нікуди не надсилається. Це важливо: у ньому зазвичай лежать облікові записи, адреси електронної пошти та коментарі.
Обережно: серіалізовані дані
WordPress зберігає частину налаштувань у wp_options і wp_postmeta у вигляді серіалізованих значень PHP, наприклад s:12:"Привіт";. Число — це довжина рядка в байтах: в UTF-8 кожна українська літера займає два байти. Зіпсований текст має іншу довжину, ніж виправлений, тому після правки число не збігається, і WordPress відкидає значення. Спершу виправляйте таблиці зі вмістом: wp_posts, wp_comments і wp_terms. Для налаштувань краще підходить wp search-replace з WP-CLI — він перераховує довжини.
Усуваємо причину в MySQL
- Переведіть таблиці та з’єднання на
utf8mb4і вкажіть уwp-config.phpрядокdefine('DB_CHARSET', 'utf8mb4');. - Якщо в стовпці
latin1лежать байти UTF-8, не конвертуйте його напряму — текст закодується вдруге. Звичайний шлях іде через двійковий тип: спочаткуMODIFY … LONGBLOB, потімMODIFY … LONGTEXT CHARACTER SET utf8mb4. - Кожну зміну спершу перевіряйте на копії бази.
Часті запитання
Чи можна виправити всю базу WordPress одразу?
Так, зокрема великі SQL-дампи. Але зважайте на серіалізовані дані в wp_options і wp_postmeta — з ними краще впорається WP-CLI.
Чи зміняться правильні символи в дампі?
Ні. Mojibuster виправляє лише явно зіпсовані послідовності. Правильний текст залишається як є.
Чим відрізняються utf8 і utf8mb4?
У MySQL utf8 зберігає символи завдовжки не більше трьох байтів, тому емодзі губляться. utf8mb4 — це справжній UTF-8, і саме він потрібен для WordPress.
Чи підійде це не лише для WordPress?
Так. У Joomla, Drupal, Magento та власних застосунків на MySQL чи MariaDB та сама проблема й те саме рішення.