« Fatal error: Uncaught Error: Call to a member function get_id() on null » : ce message apparaît dans les journaux PHP au moment précis où un client clique sur l’onglet « Commandes » de son compte, quelques secondes après avoir abandonné un paiement resté en suspens. La page reste blanche, le support reçoit un ticket, et le développeur qui ouvre les logs découvre une pile d’appels qui pointe vers un template d’espace client parfaitement banal.
Ce genre d’erreur est trompeur parce qu’elle ne se produit jamais en boutique de test avec des données propres. Il faut une commande dans un état particulier — orpheline, partiellement créée, ou associée à un identifiant qui n’existe plus dans wp_posts — pour la déclencher. Une fois qu’on comprend le mécanisme, le correctif prend cinq minutes ; le repérer en prend souvent bien plus.
Symptôme : une page blanche sur l’historique des commandes
Le rapport client est presque toujours le même : « je clique sur mon historique et ça plante ». Le code HTTP renvoyé est un 500, et le journal PHP contient une trace qui remonte à une fonction de template appelant $order->get_id(), $order->get_status() ou une méthode similaire sur une variable qui vaut null.
Dans la majorité des cas rencontrés sur des boutiques en production, le déclencheur est une commande créée par une passerelle de paiement externe (redirection vers une banque, webhook en retard) qui n’a jamais atteint l’état pending correctement, ou qui a été supprimée manuellement depuis l’administration sans que les métadonnées associées au client aient été nettoyées.
Diagnostic : remonter jusqu’à l’appel fautif
La fonction wc_get_order() est au cœur du problème. Elle est censée renvoyer un objet WC_Order, mais dès que l’identifiant passé en argument ne correspond à aucune commande valide, elle renvoie false — et non une exception. Tout code qui enchaîne un appel de méthode juste après, sans contrôle, provoque la fatale.
$order = wc_get_order( $order_id );
// Si $order_id est invalide ou supprimé, $order vaut false ici.
echo $order->get_id(); // Fatal error: Call to a member function get_id() on null/false

Pour localiser la source exacte, il est utile d’activer WP_DEBUG_LOG et de regarder la ligne précise indiquée dans wp-content/debug.log. Sur les boutiques qui utilisent un thème enfant avec des templates de compte client surchargés (typiquement woocommerce/myaccount/orders.php ou view-order.php), c’est presque toujours là que se cache l’appel non protégé.
Repérer les commandes orphelines
Une requête simple permet de confirmer l’hypothèse : chercher les entrées de la table de métadonnées client qui référencent un identifiant de commande absent de la table des commandes (ou des wp_posts de type shop_order si le stockage historique est encore actif). Une poignée de lignes suffit généralement à expliquer plusieurs semaines de tickets sporadiques.
Le correctif : vérifier avant d’appeler
Le correctif est toujours le même principe : ne jamais supposer que wc_get_order() a réussi.
$order = wc_get_order( $order_id );
if ( ! $order instanceof WC_Order ) {
// Commande introuvable : on affiche un message plutôt que de planter.
echo '<p>Cette commande n'est plus disponible.</p>';
return;
}
echo $order->get_id();
Le test instanceof WC_Order est préférable à un simple if ( $order ) car il couvre aussi le cas où une extension tierce renverrait un objet inattendu. Si le template modifié appartient à un thème enfant, il vaut mieux comparer sa version avec celle du thème parent WooCommerce le plus proche pour vérifier qu’aucune autre garde n’a été supprimée par erreur lors de la personnalisation.
Prévention : verrouiller le cycle de vie des commandes
Trois réflexes limitent fortement la récurrence de ce type d’incident :
- Ne jamais supprimer une commande manuellement depuis la base sans passer par
wc_delete_shop_order()ou l’interface d’administration, qui nettoient les métadonnées associées. - Surveiller le hook
woocommerce_order_status_pendinget journaliser les commandes qui restent bloquées plus de quelques heures dans cet état. - Ajouter un test automatisé qui charge la page « Mes commandes » avec un jeu de données incluant volontairement un identifiant invalide.
Sur chaque template d’espace client surchargé, la première ligne après
wc_get_order()devrait être un test de validité. C’est un réflexe qui coûte deux secondes à écrire et qui évite des heures de support.
Ce qu’il faut retenir
Cette fatale n’a rien d’exotique : elle sanctionne simplement une hypothèse implicite — « la commande existe forcément » — qui finit toujours par être fausse un jour, sur une boutique suffisamment fréquentée. Le correctif tient en une condition, mais encore faut-il l’avoir posée avant que le client ne tombe sur la page blanche plutôt qu’après.