# HPOS et un bloc de statistiques de vente : une requête sur l’ancien schéma

> Corriger un bloc de statistiques qui continue d'interroger l'ancien schéma de commande après l'activation du stockage optimisé WooCommerce.

- Auteur : WordPress Développement
- Publié le : 2022-11-09
- Mis à jour le : 2026-09-30
- Catégorie : Blocs Gutenberg
- URL : https://www.wpmoderne.fr/blocs/hpos-bloc-statistiques-vente-ancien-schema/

## L’essentiel

- Le bloc interrogeait directement la table wp_postmeta des commandes
- HPOS déplace les commandes vers des tables dédiées
- La correction passe par l'API CRUD de commande, compatible avec les deux schémas

**Symptôme :** juste après l'activation du stockage haute performance des commandes (HPOS) sur une boutique WooCommerce, un bloc personnalisé affichant le chiffre d'affaires du mois s'est mis à afficher zéro, alors que des commandes continuaient d'arriver normalement. Aucune erreur PHP visible, aucun message dans les journaux : juste un chiffre obstinément resté à zéro.

Ce billet retrace le diagnostic complet de ce bug et le correctif appliqué. La migration WooCommerce elle-même vers HPOS, avec ses étapes de synchronisation, relève d'un autre sujet et n'est pas traitée ici.

## Diagnostic : d'où vient réellement le zéro

Le bloc, développé avant l'existence de HPOS, interrogeait directement la table `wp_postmeta` pour additionner le montant total des commandes du mois, en filtrant sur la méta-donnée `_order_total` attachée à des articles du type `shop_order` :

```
global $wpdb;
$total = $wpdb->get_var( "
    SELECT SUM(meta_value)
    FROM {$wpdb->postmeta}
    WHERE meta_key = '_order_total'
    AND post_id IN (
        SELECT ID FROM {$wpdb->posts}
        WHERE post_type = 'shop_order'
        AND post_date >= '2022-11-01'
    )
" );
```

Ce code fonctionnait très bien tant que WooCommerce stockait les commandes comme des articles classiques dans `wp_posts` et `wp_postmeta`. Une fois HPOS activé, les nouvelles commandes ne sont plus créées dans ces tables du tout : elles vivent désormais dans des tables dédiées, `wp_wc_orders` et ses tables associées. La requête SQL du bloc continuait de chercher des commandes dans `wp_posts`, là où elles n'apparaissaient tout simplement plus.

> L'essentiel à retenir : Le bloc interrogeait directement la table wp_postmeta des commandes ; HPOS déplace les commandes vers des tables dédiées ; La correction passe par l'API CRUD de commande, compatible avec les deux schémas

## Correctif : passer par l'API CRUD de commande

La correction ne consiste pas à réécrire la requête SQL pour cibler les nouvelles tables directement, ce qui recréerait la même fragilité en cas de futur changement de schéma. La bonne approche s'appuie sur l'API CRUD de commande fournie par WooCommerce, compatible avec les deux schémas de stockage sans distinction dans le code du bloc :

```
function calculer_ca_du_mois() {
    $commandes = wc_get_orders( array(
        'status'       => array( 'wc-completed', 'wc-processing' ),
        'date_created' => '>=' . strtotime( 'first day of this month' ),
        'limit'        => -1,
    ) );

    $total = 0;
    foreach ( $commandes as $commande ) {
        $total += $commande->get_total();
    }
    return $total;
}
```

Cette fonction s'appuie sur `wc_get_orders()` et sur la méthode `get_total()` de l'objet commande, tous deux garantis par WooCommerce de fonctionner indifféremment que HPOS soit activé ou non. Le bloc n'a plus jamais besoin de savoir où sont physiquement stockées les commandes.

## Prévention : comment éviter ce piège à l'avenir

- Ne jamais interroger directement `wp_posts` ou `wp_postmeta` pour des données de commande WooCommerce
- Toujours passer par l'API CRUD fournie (`wc_get_order()`, `wc_get_orders()`) pour toute lecture ou écriture
- Déclarer explicitement la compatibilité HPOS de toute extension personnalisée via `FeaturesUtil::declare_compatibility()`

```
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
        );
    }
} );
```

## Un test simple à ne jamais sauter

Sur tout site WooCommerce actif, tester un bloc de statistiques sur un environnement de recette avec HPOS activé avant toute mise en production évite ce genre de surprise. Le comportement en mode compatible (avec synchronisation entre ancien et nouveau schéma) peut masquer temporairement le problème, jusqu'à ce que la synchronisation soit désactivée.

> Toute requête SQL qui cible directement les tables internes de WooCommerce mérite d'être considérée comme fragile par construction, quelle que soit l'ancienneté du code : l'API CRUD existe précisément pour absorber ce genre de changement de schéma.

## En résumé

Un bloc qui interroge directement les tables internes de WooCommerce cassera tôt ou tard, dès que le schéma de stockage évolue. S'appuyer systématiquement sur l'API CRUD de commande, plutôt que sur des requêtes SQL directes, protège durablement contre ce type de rupture silencieuse.
