30 minutes : c’est, par défaut, la durée de vie d’une session PHP inactive sur de nombreuses configurations d’hébergement, avant que son contenu ne soit purgé automatiquement. Ce chiffre suffit à expliquer une catégorie récurrente de commandes perdues : celles où l’identifiant de la commande en cours n’était conservé qu’en session, jamais ailleurs.
Ce qu’on voit
Le symptôme est presque toujours le même : un client commence une commande, quitte la page de paiement pour vérifier un détail — souvent en ouvrant un nouvel onglet ou en changeant de réseau, ce qui provoque parfois une nouvelle session côté serveur — puis revient plus tard pour finaliser son achat. À son retour, le tunnel de commande repart de zéro, sans trace de la commande commencée, alors même que celle-ci existe bel et bien en base de données avec un statut « en attente ».
Dans le code d’une extension personnalisée à l’origine de ce comportement, on retrouve typiquement une ligne de ce type, censée retrouver la commande en cours :
$order_id = WC()->session->get( 'commande_en_cours_id' );
Pourquoi c’est un problème
La session gérée par WooCommerce via WC_Session_Handler repose sur un cookie identifiant la session côté client, associé à des données stockées côté serveur — historiquement dans une table dédiée, ou selon la configuration dans un système de cache. Cette session est conçue pour disparaître : c’est son rôle, elle ne doit pas devenir un mécanisme de persistance à long terme. Un changement d’appareil, une navigation privée, un cookie effacé par un bloqueur de traqueurs, ou simplement l’expiration naturelle de la session suffisent à rendre cette clé introuvable, alors que la commande, elle, continue d’exister dans la table des commandes.
Ce problème est aggravé sur les configurations où la session est stockée dans un cache objet volatile, comme certaines configurations Redis avec politique d’éviction agressive : la session peut disparaître encore plus tôt que prévu si le serveur de cache manque de mémoire disponible.

Quoi faire à la place
L’identifiant d’une commande en cours doit être retrouvable indépendamment de toute session, à partir d’une information stable : le compte client connecté, ou un jeton persistant transmis dans l’URL de retour de la commande. La bonne pratique consiste à écrire cet identifiant en méta-donnée sur la commande elle-même, via update_meta_data(), et à le retrouver par une requête sur cette méta plutôt que par la session.
$order = wc_get_order( $order_id );
$order->update_meta_data( '_jeton_reprise_commande', $jeton );
$order->save();
// Plus tard, pour retrouver la commande à partir du jeton :
$commandes = wc_get_orders( [
'meta_key' => '_jeton_reprise_commande',
'meta_value' => $jeton,
'limit' => 1,
] );
Avec le stockage des commandes en tables dédiées (HPOS, activable depuis WooCommerce 8.2 et devenu la valeur par défaut sur les nouvelles installations à partir de WooCommerce 8.2), cette recherche par méta reste prise en charge par wc_get_orders(), qui redirige la requête vers la structure de stockage active sans changement de code côté développeur.
Ce qui reste vrai malgré tout pour la session
- La session reste parfaitement adaptée au panier en cours de construction, tant qu’aucune commande n’a encore été créée.
- Elle convient à des données réellement temporaires, comme un indicateur d’affichage d’une bannière déjà vue.
- Elle ne doit jamais devenir la seule source de vérité pour retrouver une commande déjà enregistrée en base.
Un cas particulier : les commandes créées par une tâche planifiée
Ce piège se manifeste aussi, sous une forme différente, lorsqu’une commande est générée par une tâche exécutée via Action Scheduler plutôt que par une visite directe du client — un renouvellement d’abonnement, par exemple. Dans ce contexte, il n’existe tout simplement aucune session PHP associée à l’exécution de la tâche, puisque celle-ci ne provient d’aucune requête HTTP d’un visiteur. Un code qui suppose la présence d’une session pour retrouver ou compléter une commande créée dans ce contexte échoue systématiquement, ce qui rend l’erreur encore plus difficile à repérer en test manuel, un test réalisé depuis un navigateur disposant toujours d’une session active.
En résumé
La confusion entre donnée de session et donnée persistante coûte cher précisément parce qu’elle ne se voit pas en test rapide, effectué sans interruption de session par le développeur lui-même. Une méta-donnée écrite sur la commande, retrouvable par une requête classique, élimine cette classe entière de commandes perdues, quel que soit le comportement du navigateur ou du réseau du client entre deux visites.