WooCommerce / HPOS
HPOS WooCommerce : problèmes fréquents avec le code personnalisé
Réponse courte
Avec HPOS comme stockage principal, les commandes vivent dans wp_wc_orders et ses tables associées, pas dans wp_posts et wp_postmeta. Le code qui lit ou écrit les commandes avec les fonctions d’articles, WP_Query ou du SQL sur les tables d’articles cesse de fonctionner, souvent en silence, en renvoyant des valeurs vides. Réécrivez-le avec l’API des commandes (wc_get_order(), wc_get_orders(), $order->get_meta(), $order->update_meta_data() puis $order->save()), mettez à jour les hooks d’administration pour le nouvel écran des commandes et déclarez la compatibilité HPOS dans vos extensions.
Symptômes
- Les métadonnées de commande lues par le code sur mesure reviennent vides après l’activation de HPOS.
- Des colonnes, filtres ou meta boxes personnalisés manquent dans le nouvel écran des commandes.
- Les exports, rapports ou intégrations n’incluent plus les nouvelles commandes.
- Les valeurs enregistrées par le code sur mesure n’apparaissent pas sur la commande, ou disparaissent à l’enregistrement suivant.
- WooCommerce signale des extensions actives incompatibles et refuse de passer à HPOS.
Causes les plus fréquentes
| Motif | Pourquoi cela casse |
|---|---|
get_post_meta( $order_id, '_my_key', true ) |
Lit wp_postmeta, qui n’est pas la source de vérité avec HPOS |
update_post_meta( $order_id, … ) |
Écrit dans le stockage par articles ; HPOS ne le voit pas, ou la synchronisation l’écrase |
new WP_Query( [ 'post_type' => 'shop_order' ] ) / get_posts() |
Interroge wp_posts, où les nouvelles commandes peuvent ne pas exister |
Requêtes $wpdb sur wp_posts / wp_postmeta pour les commandes |
Ancien schéma codé en dur |
wp_insert_post() / wp_update_post() sur des commandes |
Contourne les data stores des commandes |
manage_edit-shop_order_columns uniquement |
Hooks de l’ancien écran ; l’écran HPOS en utilise d’autres |
add_meta_box( …, 'shop_order' ) |
Mauvais identifiant d’écran pour l’écran d’édition HPOS |
Diagnostic
1. Vérifiez quel stockage fait autorité
WooCommerce → Réglages → Avancé → Fonctionnalités indique si les commandes sont stockées dans les tables HPOS ou dans les anciennes tables d’articles, et si le mode de compatibilité garde les deux synchronisés. Tant que la synchronisation est active, l’ancien code peut sembler fonctionner en lecture, ce qui masque le problème jusqu’à sa désactivation.
2. Cherchez dans le code
Cherchez dans le thème, les extensions sur mesure, les mu-plugins et les extensions de snippets :
$ grep -rnE "get_post_meta|update_post_meta|delete_post_meta|wp_insert_post|wp_update_post" wp-content/themes/my-theme wp-content/plugins/my-plugin
$ grep -rnE "shop_order|wp_posts|wp_postmeta|post_type *=" wp-content/themes/my-theme wp-content/plugins/my-pluginChaque résultat demande une décision : touche-t-il aux commandes ? Le code des produits et des pages n’est pas concerné.
3. Vérifiez les extensions
WooCommerce liste les extensions incompatibles sur l’écran des Fonctionnalités. Pour chacune, vérifiez si une mise à jour déclare la compatibilité ; sinon, interrogez l’éditeur ou prévoyez un remplacement.
4. Testez en préproduction avec la synchronisation activée, puis désactivée
Activez HPOS en préproduction avec le mode de compatibilité, déroulez les parcours critiques (checkout, notifications de paiement, e-mails, modifications dans l’administration, exports, intégrations), puis désactivez la synchronisation et recommencez. Du code qui ne fonctionne qu’avec la synchronisation activée n’est pas compatible.
Journaux et vérifications techniques
- L’écran des Fonctionnalités : stockage principal, état de la synchronisation, extensions incompatibles.
- WooCommerce → État → Journaux :
fatal-errorsaprès le changement de stockage. - Notes et métadonnées des commandes de test, comparées avant et après le changement.
- Comparaisons en lecture seule d’une même commande dans les deux stockages tant que la synchronisation est active.
Solutions
Lisez et écrivez les commandes via l’API des commandes
// Lire
$order = wc_get_order( $order_id );
if ( ! $order ) {
return;
}
$po_number = $order->get_meta( '_po_number' );
// Écrire : rien n’est enregistré avant l’appel à save()
$order->update_meta_data( '_po_number', sanitize_text_field( $value ) );
$order->save();
// Interroger
$orders = wc_get_orders( [
'status' => [ 'wc-processing' ],
'limit' => 50,
'meta_query' => [
[ 'key' => '_po_number', 'compare' => 'EXISTS' ],
],
] );Prenez en charge les deux écrans d’administration
use Automattic\WooCommerce\Utilities\OrderUtil;
// Colonnes : ancien écran et écran HPOS
add_filter( 'manage_edit-shop_order_columns', 'myplugin_add_column' );
add_filter( 'manage_woocommerce_page_wc-orders_columns', 'myplugin_add_column' );
add_action( 'manage_shop_order_posts_custom_column', function ( $column, $post_id ) {
myplugin_render_column( $column, wc_get_order( $post_id ) );
}, 10, 2 );
add_action( 'manage_woocommerce_page_wc-orders_custom_column', function ( $column, $order ) {
myplugin_render_column( $column, $order );
}, 10, 2 );
// Meta box sur l’écran d’édition des commandes actif
add_action( 'add_meta_boxes', function () {
add_meta_box( 'myplugin-box', 'Bon de commande', 'myplugin_render_box', wc_get_page_screen_id( 'shop-order' ), 'side' );
} );
function myplugin_render_box( $post_or_order ) {
$order = $post_or_order instanceof WP_Post ? wc_get_order( $post_or_order->ID ) : $post_or_order;
// …
}Déclarez la compatibilité dans vos propres extensions
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 );
}
} );Ce qu’il ne faut pas faire
- Ne déclarez pas la compatibilité pour faire taire l’avertissement avant d’avoir vérifié le code.
- Ne désactivez pas le mode de compatibilité juste après la bascule : gardez-le comme voie de retour arrière jusqu’à ce que la boutique ait fonctionné correctement un certain temps.
- Ne « réparez » pas les valeurs manquantes en copiant des métadonnées entre tables en SQL.
Quand faire appel à un expert
Faites appel à un ingénieur quand l’audit trouve des accès aux commandes dispersés dans de nombreux fichiers, quand une extension indispensable n’a pas de version compatible, quand les données de commande diffèrent déjà entre les stockages, ou quand la boutique est assez grande pour que la migration elle-même doive être planifiée.
Problèmes liés
- WooCommerce / Commandes Commandes WooCommerce manquantes ou incorrectes Avant de considérer une commande comme perdue, vérifiez tous les statuts, les brouillons et le prestataire de paiement. Les totaux faux viennent souvent des taxes, frais, codes promo ou recalculs.
- WooCommerce / Erreurs Erreur fatale WooCommerce : guide de dépannage pratique Lisez correctement l’erreur fatale (fichier, ligne, trace) et rattachez-la au changement qui l’a déclenchée.
- WooCommerce / Erreurs Conflit d’extensions WooCommerce : comment trouver la cause Partez des preuves (l’erreur, le moment, la requête) et isolez en préproduction par moitiés, pas extension par extension en production.
Questions fréquentes
Comment savoir si mon code est compatible HPOS ?
Cherchez les accès directs aux commandes : get_post_meta et update_post_meta sur des identifiants de commande, WP_Query ou get_posts avec shop_order, wp_insert_post pour des commandes et du SQL sur wp_posts ou wp_postmeta pour des commandes. Le code qui n’utilise que wc_get_order, wc_get_orders et les méthodes de l’objet commande est généralement compatible.
Pourquoi ma colonne personnalisée disparaît-elle de la liste des commandes ?
L’écran des commandes HPOS est une autre page d’administration avec d’autres hooks. Les colonnes enregistrées avec manage_edit-shop_order_columns ont aussi besoin de leurs équivalents manage_woocommerce_page_wc-orders_columns.
Dois-je déclarer la compatibilité ?
Oui, pour vos propres extensions. WooCommerce utilise cette déclaration pour décider si HPOS peut être activé. Ne la déclarez qu’après avoir vérifié le code.
Puis-je encore exécuter du SQL sur les commandes ?
Préférez wc_get_orders(). Si vous avez vraiment besoin de SQL, récupérez les noms de tables auprès de WooCommerce au lieu de coder wp_posts en dur, et gardez en tête que le schéma diffère d’un stockage à l’autre.