vendredi 25 septembre 2026

À propos

Contact

Extensions

HPOS de WooCommerce : rendre votre extension compatible avec les commandes

WooCommerce migre le stockage des commandes vers des tables dédiées. Déclarez la compatibilité, remplacez les accès directs aux post meta et testez les deux modes.

Par Clément Hadrot • 15 décembre 2022 • 5 min de lecture • Aucun commentaire
HPOS de WooCommerce : rendre votre extension compatible avec les commandes

Une cliente qui gère une boutique de pièces détachées nous a contactés fin novembre parce qu’une extension de facturation qu’elle utilisait affichait des montants à zéro depuis sa dernière mise à jour de WooCommerce. Le coupable : un accès direct à get_post_meta() sur l’ID de commande, alors que WooCommerce venait d’activer le stockage haute performance des commandes sur son site. L’extension lisait une table qui n’était plus celle où vivaient les données.

High-Performance Order Storage (HPOS), aussi appelé « Custom Order Tables », change la façon dont WooCommerce range les commandes en base. Au lieu de post types stockés dans wp_posts et wp_postmeta, les commandes vivent dans des tables dédiées : wc_orders, wc_order_operational_data, wc_orders_meta, entre autres. Si votre extension touche aux commandes, il faut déclarer sa compatibilité et corriger les accès qui contournent l’API.

Comprendre ce qui change réellement

HPOS n’est pas une simple option cosmétique. Tant que le mode legacy reste actif, une commande est un objet WC_Order adossé à un article de type shop_order. Une fois HPOS activé, l’objet WC_Order existe toujours, avec les mêmes méthodes publiques, mais son stockage physique change complètement. Le compatibility layer de WooCommerce peut, pendant une période de transition, synchroniser les deux structures, mais s’appuyer là-dessus dans du code neuf est une mauvaise idée : la synchronisation peut être désactivée par le site.

Concrètement, tout code qui fait l’hypothèse qu’une commande est un article WordPress classique casse tôt ou tard : requêtes WP_Query avec post_type => 'shop_order', appels à get_post_meta( $order_id, ... ), jointures SQL directes sur wp_posts.

Déclarer la compatibilité

WooCommerce fournit un hook dédié pour annoncer qu’une extension gère correctement HPOS. Il se déclenche très tôt, avant l’initialisation de WooCommerce lui-même :

L'essentiel à retenir : Déclarer FEATURES_PLUGIN via before_woocommerce_init ; Remplacer get_post_meta par les API CRUD ; Tester en mode legacy et en mode HPOS
add_action( 'before_woocommerce_init', function() {
    if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
        \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
            'custom_order_tables',
            __FILE__,
            true
        );
    }
} );

Cette déclaration est visible dans l’écran WooCommerce → Réglages → Fonctionnalités → Compatibilité des extensions. Sans elle, WooCommerce affiche votre extension comme « non testée » et peut, selon la configuration, empêcher l’activation de HPOS tant que des extensions incompatibles sont actives.

Remplacer les accès directs par les API CRUD

Le principe central : ne jamais parler à la base directement, toujours passer par l’objet WC_Order ou par les fonctions de façade de WooCommerce. Quelques correspondances utiles :

  • get_post_meta( $order_id, '_billing_vat', true ) devient $order->get_meta( '_billing_vat', true ).
  • update_post_meta( $order_id, '_billing_vat', $valeur ) devient $order->update_meta_data( '_billing_vat', $valeur ); $order->save();.
  • get_post( $order_id )->post_status devient $order->get_status().
  • Une recherche par identifiant client passe par wc_get_orders( array( 'customer_id' => $user_id ) ) plutôt qu’une WP_Query sur shop_order.

Pour charger une commande sans hypothèse de stockage, la fonction à retenir est wc_get_order( $order_id ), qui renvoie toujours l’objet correct quel que soit le mode actif. Si votre extension fait des requêtes SQL personnalisées pour des besoins de reporting, il faut détecter le mode actif via \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled() et adapter la requête, ou mieux, utiliser wc_get_orders() avec ses filtres avancés qui couvrent la grande majorité des cas.

Le cas des metabox et des colonnes personnalisées

Si votre extension ajoute une colonne dans la liste des commandes ou une metabox dans l’écran d’édition, elle doit s’accrocher aux hooks HPOS plutôt qu’aux hooks historiques liés à l’écran edit.php. WooCommerce expose des filtres comme woocommerce_shop_order_list_table_columns et woocommerce_shop_order_list_table_custom_column, qui fonctionnent dans les deux modes, contrairement aux hooks manage_shop_order_posts_columns qui ne s’appliquent qu’au mode legacy.

Tester les deux modes avant publication

WooCommerce permet d’activer HPOS en synchronisation avec le stockage classique, ce qui donne un terrain de test confortable : WooCommerce → Réglages → Fonctionnalités, section « Stockage des commandes à haute performance ». Notre méthode pour valider une extension :

  1. Créer un jeu de commandes de test avec des statuts variés (en attente, en cours, terminée, remboursée).
  2. Activer HPOS avec synchronisation activée, vérifier que l’extension fonctionne à l’identique.
  3. Désactiver la synchronisation, forcer un environnement HPOS pur, et rejouer les mêmes scénarios.
  4. Revenir en mode legacy et confirmer qu’aucune régression n’apparaît pour les sites qui n’ont pas encore basculé.

Un piège classique concerne les jointures SQL personnalisées pour des rapports de vente : dans un environnement HPOS pur, les tables wp_postmeta ne contiennent plus les métadonnées de commande, une requête qui les cible silencieusement ne remonte rien, sans erreur visible.

Sur nos projets, la règle qu’on applique systématiquement : si le code touche à une commande, il passe par WC_Order ou wc_get_orders(), jamais par une fonction post-native. Ça évite 90 % des soucis de compatibilité HPOS avant même d’y penser.

En résumé

La compatibilité HPOS n’est pas une case à cocher isolée : elle demande de revoir chaque endroit où l’extension suppose qu’une commande est un article WordPress. Déclarez la compatibilité via FeaturesUtil::declare_compatibility(), remplacez systématiquement les accès meta directs par l’API CRUD de WC_Order, et testez réellement dans les deux modes avant de publier une mise à jour. Le jeu en vaut la chandelle : HPOS devient progressivement la norme sur les boutiques à fort volume, et une extension non déclarée compatible finira par être signalée aux utilisateurs comme un frein à la migration.

Partager :

À propos de l'auteur

Clément Hadrot

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi