Zo ziet het probleem eruit
Voor
INSERT INTO wp_posts (post_title) VALUES ('Café-menu – crème brûlée voor één');Na
INSERT INTO wp_posts (post_title) VALUES ('Café-menu – crème brûlée voor één');Waar het vandaan komt
WordPress slaat tekst op als UTF-8. Veel oudere installaties hebben hun tabellen echter als latin1 aangemaakt of verbinden met latin1. Zolang schrijven en lezen dezelfde fout maken, merkt niemand het. Na een verhuizing naar een nieuwe server, een export met phpMyAdmin of een wijziging van de verbindingstekenset wordt elke letter met accent ineens twee tekens.
DB_CHARSETinwp-config.phpstaat oplatin1of past niet bij de tabellen.- De dump is als
latin1geëxporteerd en alsutf8mb4geïmporteerd, of andersom. - Een plugin of importscript heeft al kapotte tekst nog een keer omgezet. Zo ontstaat dubbel gecodeerde tekst zoals
é.
De export herstellen
- Maak een back-up van de database voordat je iets wijzigt.
- Exporteer de betreffende tabellen als
.sql-bestand, bijvoorbeeld met phpMyAdmin ofmysqldump --default-character-set=utf8mb4. - Sleep het bestand naar het vak hierboven. Mojibuster herstelt alleen de kapotte plekken en laat elke wijziging zien.
- Download het herstelde bestand en importeer het met
utf8mb4in een lege testdatabase. - Controleer de site. Ziet alles er goed uit, importeer het dan in de live database.
De dump wordt nooit geüpload, en dat is belangrijk: er staan meestal gebruikersaccounts, e-mailadressen en reacties in. Meer daarover voor bedrijven en functionarissen voor gegevensbescherming.
Pas op met geserialiseerde gegevens
WordPress bewaart sommige instellingen in wp_options en wp_postmeta als geserialiseerde PHP-waarden, bijvoorbeeld s:5:"Café";. Het getal is de lengte in bytes. Wordt é weer é, dan klopt die lengte niet meer en gooit WordPress de waarde weg. Herstel dus eerst inhoudstabellen als wp_posts, wp_comments en wp_terms. Voor opties is wp search-replace van WP-CLI beter, want dat past de lengtes aan.
De oorzaak in MySQL oplossen
- Zet tabellen en verbinding om naar
utf8mb4en steldefine('DB_CHARSET', 'utf8mb4');inwp-config.phpin. - Staan er UTF-8-bytes in een
latin1-kolom, converteer die dan niet rechtstreeks: dat zou ze een tweede keer coderen. De gebruikelijke route loopt via een binair type: eerstMODIFY … LONGBLOB, daarnaMODIFY … LONGTEXT CHARACTER SET utf8mb4. - Test elke wijziging eerst op een kopie van de database.
Veelgestelde vragen
Kan ik een hele WordPress-database in één keer herstellen?
Ja, ook grote SQL-dumps. Let wel op geserialiseerde gegevens in wp_options en wp_postmeta: WP-CLI regelt dat beter.
Worden correcte tekens in de dump aangepast?
Nee. Mojibuster herstelt alleen reeksen die duidelijk kapot zijn. Correcte tekst blijft zoals hij is.
Wat is het verschil tussen utf8 en utf8mb4?
In MySQL slaat utf8 alleen tekens van maximaal drie bytes op, waardoor emoji verloren gaan. utf8mb4 is echte UTF-8 en de juiste keuze voor WordPress.
Werkt dit ook voor andere systemen dan WordPress?
Ja. Joomla, Drupal, Magento of je eigen applicatie op MySQL of MariaDB hebben hetzelfde probleem en dezelfde oplossing.