Jak problém vypadá
Před
INSERT INTO wp_posts (post_title) VALUES ('PĹ™Ăliš ĹľluĹĄouÄŤkĂ˝ kĹŻl – nabĂdka na vĂkend');Po
INSERT INTO wp_posts (post_title) VALUES ('Příliš žluťoučký kůl – nabídka na víkend');Odkud se to bere
WordPress ukládá text v UTF-8. Mnoho starších instalací ale vytvořilo tabulky jako latin1 nebo se k databázi připojovalo v latin1. Dokud zápis i čtení dělají stejnou chybu, nikdo si ničeho nevšimne. Po přesunu na nový server, exportu přes phpMyAdmin nebo změně kódování spojení se každé české písmeno najednou změní na dva znaky.
DB_CHARSETvwp-config.phpjelatin1nebo nesouhlasí s tabulkami.- Dump byl exportován jako
latin1a importován jakoutf8mb4– nebo naopak. - Plugin nebo importní skript převedl už poškozený text ještě jednou. Vzniká tak dvojitě zakódovaný text jako
Ä›.
Oprava exportu
- Před jakoukoli změnou zazálohujte databázi.
- Exportujte postižené tabulky do souboru
.sql, například v phpMyAdminu nebo příkazemmysqldump --default-character-set=utf8mb4. - Přetáhněte soubor do pole výše. Mojibuster opraví jen poškozená místa a ukáže každou změnu.
- Stáhněte opravený soubor a naimportujte ho jako
utf8mb4do nové testovací databáze. - Zkontrolujte web. Pokud vše vypadá správně, naimportujte data do ostré databáze.
Dump se nikdy nenahrává na server – a to je důležité, protože obvykle obsahuje uživatelské účty, e-mailové adresy a komentáře. Více pro firmy a pověřence pro ochranu osobních údajů.
Pozor na serializovaná data
WordPress ukládá část nastavení v wp_options a wp_postmeta jako serializované hodnoty PHP, například s:6:"ÄŚaj";. Číslo udává délku v bajtech. Po opravě na s:4:"Čaj"; už délka 6 nesouhlasí a WordPress takovou hodnotu zahodí. Proto nejprve opravujte tabulky s obsahem, jako wp_posts, wp_comments a wp_terms. Pro volby je lepším nástrojem wp search-replace z WP-CLI, který délky aktualizuje.
Odstranění příčiny v MySQL
- Přepněte tabulky i spojení na
utf8mb4a nastavtedefine('DB_CHARSET', 'utf8mb4');vwp-config.php. - Pokud sloupec
latin1obsahuje bajty UTF-8, nepřevádějte ho přímo – zakódovali byste ho podruhé. Obvyklá cesta vede přes binární typ: nejdřívMODIFY … LONGBLOB, potomMODIFY … LONGTEXT CHARACTER SET utf8mb4. - Každou změnu nejdřív vyzkoušejte na kopii databáze.
Časté otázky
Můžu opravit celou databázi WordPressu najednou?
Ano, i velké SQL dumpy. Pozor ale na serializovaná data v wp_options a wp_postmeta – WP-CLI si s nimi poradí lépe.
Změní se správné znaky v dumpu?
Ne. Mojibuster opravuje jen řetězce, které jsou jasně poškozené. Správný text zůstává, jak je.
Jaký je rozdíl mezi utf8 a utf8mb4?
V MySQL ukládá utf8 jen znaky do tří bajtů, takže emoji se ztrácejí. utf8mb4 je skutečné UTF-8 a pro WordPress správná volba.
Funguje to i pro jiné systémy než WordPress?
Ano. Joomla, Drupal, Magento nebo vlastní aplikace nad MySQL či MariaDB mají stejný problém a stejné řešení.