Aller au contenu

Migrer PrestaShop vers WooCommerce sur cPanel

Ce guide vous montre comment migrer une boutique PrestaShop 1.6, 1.7 ou 8.x vers WooCommerce sur un serveur cPanel, avec les deux boutiques côte à côte jusqu'à la bascule. Vous finirez avec vos produits, déclinaisons, clients et images dans WooCommerce, et chaque ancienne URL PrestaShop qui redirige vers sa nouvelle fiche produit.

Ce guide vous accompagne pour déplacer une boutique PrestaShop vers WooCommerce quand les deux tournent sur un compte d’hébergement cPanel/WHM. Bien des commerçants arrivent ici avec une boutique PrestaShop 1.6 ou 1.7 difficile à mettre à jour, et ils craignent de perdre leur catalogue, leurs comptes clients et leur positionnement dans les moteurs de recherche. Ces craintes se gèrent bien, parce que PrestaShop garde tout dans une base de données MySQL sur votre propre serveur. La réponse pratique est une conversion de données. Vous montez WooCommerce à côté de la boutique en ligne, une extension d’importation lit la base PrestaShop en lecture seule, puis une carte de redirections 301 envoie chaque ancienne URL de produit vers sa nouvelle fiche. À la fin, WooCommerce prend les commandes sur votre domaine, et les fichiers et la base de PrestaShop restent archivés juste à côté, prêts pour un retour arrière.

Ce que vous allez accomplir

  • Relever la version de PrestaShop, le préfixe des tables, les langues et la taille du catalogue, pour savoir ce que l’importation doit transporter.
  • Monter WordPress et WooCommerce sur un sous-domaine du même compte cPanel pendant que PrestaShop continue de vendre.
  • Importer produits, catégories et images avec l’extension FG PrestaShop to WooCommerce, grâce à un accès SELECT seulement à la base.
  • Écrire une carte de redirections 301 dans .htaccess pour les URL simplifiées de PrestaShop, les préfixes de langue et les liens à paramètres.
  • Installer la nouvelle boutique dans public_html pendant une courte fenêtre, tester un vrai paiement et garder un retour arrière prêt.

Prérequis

  • Un compte cPanel qui héberge la boutique PrestaShop, avec accès aux écrans Domains et MySQL Databases (ou un accès root à WHM).
  • Un accès SSH avec WP-CLI, l’outil en ligne de commande de WordPress. Vérifiez avec wp --info.
  • Un accès administrateur au back-office de PrestaShop.
  • Assez d’espace disque pour une deuxième copie de vos images de produits. Vérifiez avec du -sh ~/public_html/img/p.
  • Une sauvegarde cPanel complète. Rien ici n’écrit dans la base PrestaShop, mais la bascule déplace des fichiers.
  • Un choix d’édition pour l’importateur. L’édition gratuite importe les produits, catégories, étiquettes, images et pages de contenu. Les déclinaisons, les clients et les commandes demandent l’édition Premium, selon la page de l’extension.

Les étapes supposent que PrestaShop se trouve dans public_html, que le nom d’utilisateur cPanel est exmpl et que le préfixe des tables est ps_. Remplacez ces valeurs par les vôtres partout où elles apparaissent.

Comment ça fonctionne

PrestaShop et WooCommerce tournent tous deux sur PHP et MySQL. L’importateur ne fait que lire les tables de PrestaShop, alors vous n’avez pas à mettre PrestaShop à jour avant. Le MultiPHP Manager de cPanel permet à l’ancienne boutique de garder sa version de PHP pendant que le nouveau sous-domaine en utilise une récente.

Faut-il vraiment migrer? Restez sur PrestaShop si vous comptez sur le multiboutique (plusieurs boutiques gérées depuis un seul back-office). Restez aussi si vous dépendez de modules interentreprises (B2B) ou de place de marché sans équivalent WooCommerce. Migrez si votre contenu vit déjà dans WordPress, ou si une mise à jour 1.6 ou 1.7 bloquée reviendrait de toute façon à tout reconstruire. Une boutique PrestaShop 8 en santé, avec une équipe à l’aise, est un bon endroit où rester.

Comment les données se transposent. PrestaShop répartit chaque produit sur plusieurs tables. ps_product contient le prix, la référence et le statut. ps_product_lang contient le nom, la description et link_rewrite (le slug de l’URL), avec un rang par langue, repéré par id_lang. Les déclinaisons, soit les variantes de taille et de couleur d’un produit, vivent dans ps_product_attribute. Les catégories sont dans ps_category, les clients dans ps_customer, les commandes dans ps_orders et les fiches d’images dans ps_image.

Diagramme de correspondance de sept groupes de tables PrestaShop vers WooCommerce : ps_product et ps_product_lang deviennent des produits, ps_attribute_group et ps_attribute deviennent des attributs globaux pa_, les déclinaisons de ps_product_attribute deviennent des variations, ps_category devient les catégories de produits, les fichiers ps_image des dossiers imbriqués img/p deviennent des images de la médiathèque, ps_customer devient des utilisateurs au rôle customer et ps_orders devient l'historique des commandes, les attributs, variations, clients et commandes étant marqués comme fonctions de l'édition Premium, et le thème, les modules, les transporteurs et les règles de taxes étant refaits à la main

Dans WooCommerce, un produit avec déclinaisons devient un produit variable. Chaque déclinaison devient une variation avec sa propre UGS (unité de gestion des stocks), son prix et son stock. Les noms d’options deviennent des attributs globaux, stockés comme taxonomies pa_, par exemple pa_size.

Les images vivent dans des dossiers imbriqués. Depuis PrestaShop 1.5, l’image numéro 123 est stockée dans img/p/1/2/3/123.jpg, un dossier par chiffre, avec des copies redimensionnées comme 123-home_default.jpg à côté. L’importateur télécharge les images en HTTP depuis l’URL de la boutique que vous lui donnez. La boutique doit donc rester en ligne et hors du mode maintenance pendant l’importation.

Une boutique multilingue demande d’abord une décision côté WordPress. WooCommerce seul ne gère qu’une langue. Une boutique bilingue anglais-français a besoin d’une extension multilingue, habituellement WPML ou Polylang, chacune avec son module compagnon pour WooCommerce. L’importateur Premium offre un module complémentaire qui importe les traductions dans WPML. Faites ce choix avant d’importer.

Les mots de passe dépendent de la version de PrestaShop. PrestaShop 1.6 stockait md5(_COOKIE_KEY_ . password), un hachage qui ne fonctionne qu’avec la clé secrète de cette boutique. PrestaShop 1.7 et les versions suivantes utilisent bcrypt par la fonction PHP password_hash(). La liste de fonctions de l’importateur Premium indique que les clients peuvent se connecter à WordPress avec leur mot de passe PrestaShop. Prouvez-le sur un compte test plutôt que de le tenir pour acquis.

Étape par étape

  1. Relevez les paramètres de la base et la version. Sur PrestaShop 1.7 et 8.x, lisez app/config/parameters.php :

    grep -E "'database_(host|name|user|prefix)'" ~/public_html/app/config/parameters.php

    Résultat attendu :

        'database_host' => '127.0.0.1',
        'database_name' => 'exmpl_presta',
        'database_user' => 'exmpl_ps',
        'database_prefix' => 'ps_',

    Sur PrestaShop 1.6, lancez plutôt grep -E "_DB_(SERVER|NAME|USER|PREFIX)_|_PS_VERSION_" ~/public_html/config/settings.inc.php. La commande affiche des lignes define(...) avec les mêmes valeurs. Confirmez ensuite la version dans la base :

    mysql -u exmpl_ps -p exmpl_presta -N -e "SELECT value FROM ps_configuration WHERE name='PS_VERSION_DB';"

    Attendu : une ligne comme 8.1.7. Si MySQL répond que la table n’existe pas, utilisez le préfixe du fichier au lieu de ps_.

  2. Mesurez la boutique et listez les langues.

    mysql -u exmpl_ps -p exmpl_presta -e "SELECT (SELECT COUNT(*) FROM ps_product WHERE active=1) AS products, (SELECT COUNT(*) FROM ps_product_attribute) AS combinations, (SELECT COUNT(*) FROM ps_customer WHERE deleted=0) AS customers, (SELECT COUNT(*) FROM ps_orders) AS orders;"
    mysql -u exmpl_ps -p exmpl_presta -e "SELECT l.id_lang, l.iso_code, l.active, c.value IS NOT NULL AS is_default FROM ps_lang l LEFT JOIN ps_configuration c ON c.name='PS_LANG_DEFAULT' AND c.value=l.id_lang;"

    Attendu : un rang de totaux comme 412 | 1830 | 2917 | 6204, puis un rang par langue. Un total combinations différent de zéro veut dire qu’il vous faut Premium pour les variations. Plus d’une langue active veut dire que le choix entre WPML et Polylang, décrit plus haut, passe en premier. Notez l’id_lang dont is_default vaut 1 ; la carte de redirections s’en sert.

  3. Vérifiez comment les mots de passe des clients sont stockés.

    mysql -u exmpl_ps -p exmpl_presta -e "SELECT LENGTH(passwd) AS hash_length, COUNT(*) FROM ps_customer WHERE deleted=0 AND is_guest=0 GROUP BY hash_length;"

    Attendu : des rangs à 60 (bcrypt) et parfois à 32 (l’ancien format md5). PrestaShop 1.7 et suivants remplacent un ancien hachage à la prochaine connexion du client. Une boutique mise à jour depuis 1.6 montre donc souvent les deux. Les clients du groupe 32 sont ceux qui auront le plus probablement besoin d’une réinitialisation.

  4. Montez WordPress et WooCommerce sur un sous-domaine. Dans cPanel, ouvrez Domains, créez new.example.com et notez sa racine de documents (Document Root). Les étapes supposent le réglage par défaut récent de cPanel, ~/new.example.com, hors de public_html. Si cPanel l’a placée dans public_html, changez-la avant l’installation. Sinon, l’échange de dossiers de l’étape 10 déplacera la nouvelle boutique avec l’ancienne. Créez une base vide et un utilisateur pour WordPress dans MySQL Databases, par exemple exmpl_wp et exmpl_wpuser. Installez ensuite :

    cd ~/new.example.com
    wp core download
    wp config create --dbname=exmpl_wp --dbuser=exmpl_wpuser --dbpass='REPLACE_ME'
    wp core install --url=https://new.example.com --title='Example Shop' \
      --admin_user=admin --admin_email=you@example.com --skip-email
    wp rewrite structure '/%postname%/' --hard
    wp plugin install woocommerce --activate

    Attendu : Success: WordPress installed successfully., Success: Rewrite structure set., puis Plugin 'woocommerce' activated. WooCommerce doit être actif avant de lancer l’importateur. Ses fiches produits utilisent /product/<slug>/ par défaut, et c’est ce que vise la carte de redirections.

  5. Donnez à l’utilisateur de la base WordPress un accès en lecture seule à PrestaShop. Les deux bases sont sur le même serveur MySQL, sous le même compte, alors un seul droit suffit.

    uapi Mysql set_privileges_on_database user=exmpl_wpuser database=exmpl_presta privileges=SELECT

    Lancez-la en tant qu’utilisateur cPanel ; en root, ajoutez --user=exmpl après uapi. Attendu : un bloc YAML qui contient status: 1. Avec SELECT seulement, un mauvais réglage de l’importateur ne peut modifier aucun rang de PrestaShop.

  6. Lancez l’importateur.

    wp plugin install fg-prestashop-to-woocommerce --activate

    Attendu : Plugin 'fg-prestashop-to-woocommerce' activated. Pour Premium, installez plutôt son fichier zip. Dans l’administration WordPress, ouvrez Outils > Importer > PrestaShop. Entrez l’URL de la page d’accueil de la boutique (https://example.com), l’hôte relevé à l’étape 1, la base exmpl_presta, l’utilisateur exmpl_wpuser, son mot de passe et le préfixe ps_. Testez la connexion, lancez l’importation et gardez l’onglet ouvert jusqu’à la fin. Comptez ensuite ce qui est arrivé :

    wp post list --post_type=product --post_status=publish --format=count
    wp post list --post_type=product_variation --format=count
    wp term list product_cat --format=count

    Attendu : un nombre de produits proche des produits actifs de l’étape 2, un nombre de variations proche des déclinaisons (zéro avec l’édition gratuite) et un nombre de catégories proche de celui de PrestaShop. Vérifiez que les slugs correspondent à link_rewrite, puisque les redirections en dépendent :

    wp post list --post_type=product --fields=ID,post_name --posts_per_page=3

    Attendu : des slugs comme mug-best-day qu’on retrouve dans vos anciennes URL de produits.

  7. Confirmez que les images ont suivi. Comptez les fichiers d’images originaux, sans les copies redimensionnées, et comparez avec les fichiers joints dans WordPress :

    mysql -u exmpl_ps -p exmpl_presta -N -e "SELECT COUNT(*) FROM ps_image;"
    find ~/public_html/img/p -type f -regex '.*/[0-9]+\.jpg' | wc -l
    wp post list --post_type=attachment --post_status=inherit --format=count

    Attendu : trois nombres du même ordre. Un total WordPress beaucoup plus bas veut dire que l’importateur n’a pas pu récupérer les images ; voyez la section Dépannage.

  8. Générez la carte de redirections. L’URL de produit par défaut de PrestaShop est /{category}/{id}-{rewrite}.html. Les versions 1.7 et suivantes peuvent y ajouter un ID de déclinaison, comme dans /home/12-45-mug-best-day.html. Les boutiques multilingues ajoutent /en/ ou /fr/ devant. Quand les URL simplifiées sont désactivées, les liens ressemblent à /index.php?id_product=12&controller=product.

    Diagramme des formes d'URL PrestaShop associées aux règles de redirection : les URL simplifiées avec préfixe de langue et les URL avec ID de déclinaison sont captées par une RewriteRule par produit, les URL à paramètres avec id_product sont captées par RewriteCond sur QUERY_STRING, et toutes aboutissent à la fiche produit WooCommerce avec une 301, le bloc étant placé au-dessus de BEGIN WordPress, suivi d'une bascule en quatre gestes, soit fermer la boutique, échanger les dossiers, réécrire le domaine et tester, avec un retour arrière qui remet les dossiers en place

    Exportez les ID et les slugs de la langue par défaut (remplacez id_lang=1 par votre valeur de l’étape 2), puis transformez chaque rang en règles :

    mysql -u exmpl_ps -p exmpl_presta -N -e "SELECT p.id_product, pl.link_rewrite FROM ps_product p JOIN ps_product_lang pl ON pl.id_product=p.id_product AND pl.id_shop=1 AND pl.id_lang=1 WHERE p.active=1 ORDER BY p.id_product;" > ~/ps-products.tsv
    awk -F'\t' '{
      printf "RewriteRule ^([a-z]{2}/)?(.+/)?%s(-[0-9]+)?-%s(-[0-9]+)?\\.html$ https://example.com/product/%s/ [R=301,L]\n", $1, $2, $2
      printf "RewriteCond %%{QUERY_STRING} (^|&)id_product=%s(&|$)\n", $1
      printf "RewriteCond %%{QUERY_STRING} (^|&)controller=product(&|$)\n"
      printf "RewriteRule ^(index\\.php)?$ https://example.com/product/%s/? [R=301,L]\n", $2
    }' ~/ps-products.tsv > ~/ps-redirects.conf
    head -4 ~/ps-redirects.conf

    Attendu :

    RewriteRule ^([a-z]{2}/)?(.+/)?12(-[0-9]+)?-mug-best-day(-[0-9]+)?\.html$ https://example.com/product/mug-best-day/ [R=301,L]
    RewriteCond %{QUERY_STRING} (^|&)id_product=12(&|$)
    RewriteCond %{QUERY_STRING} (^|&)controller=product(&|$)
    RewriteRule ^(index\.php)?$ https://example.com/product/mug-best-day/? [R=301,L]

    La première règle capte le produit avec ou sans préfixe de langue, chemin de catégorie, ID de déclinaison ou code-barres EAN13 à la fin. Les trois suivantes gèrent les liens à paramètres, que la directive Redirect simple d’Apache ne voit pas. Le ? à la fin de la cible retire l’ancienne chaîne de paramètres.

    Dans une boutique bilingue, cette carte envoie les URL françaises vers le produit de la langue par défaut. Quand chaque traduction aura sa propre adresse, refaites l’exportation avec l’id_lang du français et une règle ^fr/. L’édition Premium peut aussi rediriger elle-même les anciennes URL ; si vous utilisez cette fonction, sautez cette étape mais faites quand même les tests plus bas.

    Collez les règles dans ~/new.example.com/.htaccess au-dessus de # BEGIN WordPress, avec des lignes écrites à la main pour les catégories et les pages de contenu :

    # --- PrestaShop legacy URLs: keep above the WordPress block ---
    RewriteEngine On
    RewriteRule ^([a-z]{2}/)?3-mugs/?$ https://example.com/product-category/mugs/ [R=301,L]
    RewriteRule ^([a-z]{2}/)?content/4-about-us/?$ https://example.com/about-us/ [R=301,L]
    # ...rest of ps-redirects.conf...
    # --- end PrestaShop legacy URLs ---
    
    # BEGIN WordPress

    L’emplacement compte. Le bloc WordPress commence par RewriteRule ^index\.php$ - [L], qui arrête le traitement des requêtes vers index.php. Les règles à paramètres placées en dessous ne s’exécutent donc jamais.

  9. Refaites les taxes, la livraison et les paiements. La liste de fonctions de l’importateur ne comprend ni les règles de taxes, ni les transporteurs, ni les modules de paiement. Configurez-les à la main dans WooCommerce avant la bascule. Pour une boutique canadienne, suivez notre guide sur les taux de taxes WooCommerce pour la TPS, la TVH et la TVQ. Notre audit préalable à une migration WooCommerce liste les vérifications de passerelles de paiement et de webhooks à régler d’abord. Passez une commande test sur new.example.com avec chaque mode de paiement avant de continuer.

  10. Faites la bascule. Lancez une dernière importation pour mettre à jour les produits et commandes récents. Notez ensuite la dernière commande, pour repérer celles passées pendant l’échange :

    mysql -u exmpl_ps -p exmpl_presta -e "SELECT MAX(id_order), MAX(date_add) FROM ps_orders;"

    Attendu : un rang avec l’ID et l’heure de la commande la plus récente. Dans le back-office PrestaShop, réglez Paramètres de la boutique > Paramètres généraux > Maintenance > Activer la boutique à Non (en 1.6, Préférences > Maintenance). Échangez ensuite les dossiers :

    cd ~
    mkdir prestashop-archive
    mv public_html/* public_html/.htaccess prestashop-archive/
    mv new.example.com/* new.example.com/.htaccess public_html/
    cd ~/public_html
    wp search-replace 'https://new.example.com' 'https://example.com' --all-tables
    wp option get siteurl

    Attendu : un tableau de remplacements qui se termine par une ligne comme Success: Made 3412 replacements., puis https://example.com. WP-CLI garde intacts les réglages sérialisés de WordPress, qu’un REPLACE en SQL briserait. Relancez la requête MAX(id_order) ; un nombre plus élevé est une commande à ressaisir à la main.

    Les deux boutiques vivent sur un seul compte, alors le DNS ne change pas. Si WooCommerce tourne sur un autre serveur, baissez le TTL (la durée pendant laquelle les résolveurs gardent l’enregistrement en cache) à 300 secondes la veille. Changez l’enregistrement A pendant la fenêtre et vérifiez avec dig +short example.com, qui doit afficher la nouvelle adresse IP.

    Retour arrière. Si le paiement échoue et que vous ne pouvez pas corriger vite, inversez l’échange. Déplacez le contenu de public_html dans un dossier woo-failed, remettez prestashop-archive en place et réglez Activer la boutique à Oui. La base PrestaShop n’a jamais été modifiée, donc la boutique revient telle qu’elle était. Les commandes prises dans WooCommerce entre-temps doivent être ressaisies.

  11. Testez les connexions des clients. Connectez-vous sur /my-account/ avec un vrai client du groupe 60 et un du groupe 32 de l’étape 3. Si l’un des tests échoue, envoyez un lien de réinitialisation à tous les comptes clients. Bien des serveurs cPanel plafonnent le nombre de courriels qu’un domaine peut envoyer par heure. La première ligne découpe donc les identifiants des clients en fichiers de 200, et la deuxième envoie le premier fichier :

    wp user list --role=customer --field=ID | split -l 200 - ~/reset-batch-
    xargs wp user reset-password < ~/reset-batch-aa

    Attendu : une ligne Reset password for ... par utilisateur du lot, puis une ligne Success:. Une heure plus tard, relancez la deuxième ligne avec reset-batch-ab, puis reset-batch-ac, jusqu’au dernier fichier listé par ls ~/reset-batch-*. Ces commandes visent l’ensemble des clients, pas seulement le groupe en échec. Prévenez vos clients avant l’envoi des courriels, pour qu’ils ne les prennent pas pour de l’hameçonnage.

Valider que ça fonctionne

Testez chaque forme d’URL sur un produit connu :

for u in '/home/12-mug-best-day.html' '/en/home/12-45-mug-best-day.html' '/index.php?id_product=12&controller=product'; do
  printf '%s  %s\n' "$(curl -s -o /dev/null -w '%{http_code} %{redirect_url}' "https://example.com$u")" "$u"
done

Attendu : trois lignes qui commencent chacune par 301 https://example.com/product/mug-best-day/. Vérifiez ensuite qu’aucun contenu ne pointe encore vers les chemins d’images de PrestaShop :

wp db query "SELECT COUNT(*) FROM wp_posts WHERE post_status='publish' AND post_content LIKE '%/img/p/%';" --skip-column-names

Attendu : 0. Terminez par une vraie commande sur le domaine en ligne, payée puis remboursée, et confirmez que le courriel de commande arrive.

Dépannage

  • L’importateur ne se connecte pas. Le droit de l’étape 5 manque ou le préfixe est faux. Testez avec mysql -u exmpl_wpuser -p exmpl_presta -e "SHOW TABLES LIKE 'ps_product';", qui doit afficher le nom de la table. Si 127.0.0.1 échoue, essayez localhost.
  • Les produits sont importés, mais pas les images. La FAQ de l’extension précise que le champ URL doit contenir la page d’accueil de la boutique et que le mode maintenance doit être désactivé. Une redirection de http vers https, une vérification Cloudflare ou la protection contre le hotlinking de cPanel peuvent aussi bloquer les téléchargements. Corrigez, puis relancez l’importation.
  • Les produits n’ont pas d’options de taille ou de couleur. Les déclinaisons et les attributs sont des fonctions Premium. L’édition gratuite importe chaque produit sans ses variantes.
  • L’importation s’arrête en chemin. Ajoutez define('WP_MEMORY_LIMIT', '2G'); dans wp-config.php et relancez. Selon la FAQ de l’extension, une nouvelle exécution reprend là où la précédente s’est arrêtée.
  • Les anciennes URL renvoient une 404 après la bascule. Le bloc de redirections est sous # BEGIN WordPress. Vérifiez avec grep -n 'BEGIN WordPress\|PrestaShop legacy' ~/public_html/.htaccess ; le numéro de ligne du bloc PrestaShop doit être le plus petit.

Quand ce n’est pas la bonne approche

Si la valeur de la boutique repose sur des modules, l’importation du catalogue est la partie facile. Un module de place de marché, un système de listes de prix B2B ou un paiement sur mesure demande son propre plan WooCommerce, réglé avant de fixer une date de bascule.

Les configurations multiboutiques et les boutiques en quatre langues ou plus représentent un projet plus gros que ce guide. Dans ces cas, passer à une version de PrestaShop encore prise en charge peut coûter moins cher qu’un changement de plateforme. La référence mod_rewrite d’Apache documente les directives RewriteCond et RewriteRule utilisées plus haut.

Un WordPress qui rapporte vraiment mérite un opérateur — Stack Harbor opère cette pile sous WordPress Entreprise ; réservez une consultation d’infrastructure.