Scène classique : vous avez fini la refonte d'un site WordPress en staging (https://staging.exemple.fr), il faut le pousser en production (https://www.exemple.fr). Vous exportez la base, vous remplacez l'ancienne URL par la nouvelle avec un sed bien rude, vous ré-importez. Et là, les widgets Elementor disparaissent, les options de thème ne sauvegardent plus, certains champs ACF sont vides. Bienvenue dans l'enfer des données sérialisées PHP.

Le piège invisible : PHP serialize()

WordPress stocke beaucoup de choses sous forme d'arrays ou d'objets PHP sérialisés dans wp_options (option_value), wp_postmeta (meta_value), wp_usermeta, et les tables custom de la plupart des plugins. La sérialisation encode la longueur exacte de chaque chaîne de caractères. Exemple concret :

a:1:{s:8:"site_url";s:27:"https://staging.exemple.fr";}

Le s:27 signifie : "chaîne de 27 caractères". Si vous remplacez bêtement https://staging.exemple.fr (27 car.) par https://www.exemple.fr (23 car.) avec un UPDATE SQL ou un sed sur le dump, vous obtenez :

a:1:{s:8:"site_url";s:27:"https://www.exemple.fr";}  ← compteur cassé

PHP n'arrive plus à dé-sérialiser ce blob. unserialize() renvoie false, le widget affiche du vide, le plugin pense que l'option n'existe pas, WordPress retombe sur la valeur par défaut. Le pire ? Aucune erreur visible. Vos visiteurs voient un site qui marche à 80 %, et vous passez trois jours à chercher.

Pourquoi WP-CLI search-replace est la bonne réponse

La commande wp search-replace de WP-CLI fait ce qu'il faut : elle dé-sérialise chaque valeur, applique le remplacement à l'intérieur des chaînes, re-sérialise proprement avec le bon compteur de longueur. Idem pour les objets PHP, les arrays imbriqués, et même les doubles sérialisations qu'on trouve parfois.

Sauf que. WP-CLI exige un accès SSH, exige PHP en ligne de commande, et tous les hébergements mutualisés français ne le proposent pas. Pour les utilisateurs qui n'ont qu'un cPanel et un phpMyAdmin, le module Search & Replace d'Alesta AI fait exactement le même travail, depuis l'interface admin WordPress.

Ce que fait le module Search & Replace d'Alesta AI

Architecture en trois étapes, qu'on a piochée chez les outils de référence du marché et adaptée pour rester compatible PHP 7.4 :

  1. Détection des tables et colonnes texte : on parcourt information_schema pour repérer les colonnes text, longtext, varchar susceptibles de contenir des URLs ou des données sérialisées.
  2. Traitement par lots : on lit 500 lignes à la fois, on désérialise chaque meta_value ou option_value avec un maybe_unserialize() récursif, on remplace, on re-sérialise, on UPDATE uniquement les lignes qui ont changé.
  3. Mode dry-run obligatoire : avant tout remplacement réel, le module affiche combien d'occurrences trouvées dans combien de lignes dans combien de tables. Aucune écriture en BDD. Vous validez, et seulement après vous lancez l'apply.
"

La règle d'or des migrations WordPress : on ne fait jamais de search-replace direct en SQL. Jamais. Même si "c'est juste une petite chaîne".

Cas d'usage 1 — Migration staging → production

Le cas le plus courant. Vous avez bossé sur https://staging.exemple.fr, vous voulez pousser sur https://www.exemple.fr. Procédure :

  1. Cloner la BDD staging vers la production (export SQL + import).
  2. Activer le module Search & Replace, mode dry-run, chercher https://staging.exemple.fr, remplacer par https://www.exemple.fr.
  3. Vérifier le rapport : en général 1 200 à 3 000 occurrences sur un site standard (options, postmeta Elementor, ACF, customizer).
  4. Lancer l'apply. Le module met à jour, garde un historique des 5 dernières opérations avec compteur de lignes touchées.

Cas d'usage 2 — Passage en HTTPS

Vous venez d'installer un certificat SSL gratuit (Let's Encrypt). Tout votre site est en http:// en dur dans les widgets, dans les sliders, dans les images de background CSS Elementor. Même opération : dry-run sur http://exemple.frhttps://exemple.fr, validation, apply. Compter ~5 000 occurrences sur un site e-commerce moyen.

Cas d'usage 3 — Ajout du préfixe www

Subtil : vous voulez passer de https://exemple.fr à https://www.exemple.fr. C'est exactement le scénario où on a, dans Alesta AI v1.3.4, chaîné automatiquement le module WWW (qui réécrit .htaccess) avec Search & Replace (qui met à jour la BDD). Avant v1.3.4 : les utilisateurs cochaient "ajouter le www" et leur site cassait à moitié parce que les vieilles URLs restaient en BDD. Maintenant, les deux opérations se font dans la même transaction : le .htaccess n'est mis à jour que si le search-replace est passé.

Ce qu'il ne faut pas faire (la liste)

  • Ne pas faire UPDATE wp_options SET option_value = REPLACE(option_value, 'ancien', 'nouveau'). Vous corromprez tout ce qui est sérialisé.
  • Ne pas faire un sed -i sur un dump SQL. Même problème, même résultat.
  • Ne pas faire de search-replace sur des sites multilingues avant d'avoir lu la documentation de votre plugin de traduction (WPML/Polylang stockent des relations dans des tables custom avec leurs propres règles).
  • Toujours sauvegarder la BDD avant. Toujours. Le module Alesta crée un export .sql.gz automatique avant chaque apply, mais une sauvegarde externe ne fait jamais de mal.

Combien de temps ?

Sur une base de 1 000 articles + 50 pages Elementor + WooCommerce avec 500 produits, le dry-run prend ~12 secondes, l'apply ~40 secondes. Sur une base à 50 000 lignes d'options et postmeta cumulées, comptez 2 à 3 minutes. Le module montre une barre de progression et un compteur live des tables traitées.