# register_meta et les valeurs par défaut d’une méta de commande jamais initialisée

> Une ancienne commande n'a jamais reçu la méta ajoutée l'an dernier. Plutôt que de multiplier les vérifications, register_meta() peut fournir une valeur par défaut fiable.

- Auteur : WordPress Développement
- Publié le : 2022-06-25
- Mis à jour le : 2022-06-25
- Catégorie : E-commerce
- URL : https://www.wpmoderne.fr/ecommerce/register-meta-valeur-defaut-meta-commande-woocommerce/

## L’essentiel

- register_meta() accepte un paramètre default depuis WordPress 5.5
- La valeur par défaut ne s'applique qu'à get_metadata(), pas en base
- Elle évite de dupliquer des vérifications isset() partout dans le code

Que renvoie `$order->get_meta( 'canal_origine' )` pour une commande passée avant l'ajout de cette méta au tunnel d'achat ? Une chaîne vide. Et une chaîne vide n'est pas toujours équivalente à une absence de valeur dans la logique métier qui l'exploite ensuite, notamment quand un rapport doit distinguer « canal inconnu » d'un canal réellement vide.

C'est le genre de détail qui ne pose aucun problème tant que la boutique est jeune, puis qui se rappelle au développeur trois ans plus tard, au moment d'exploiter un historique de commandes hétérogène.

## Le piège des vérifications dispersées

La réaction la plus fréquente consiste à parsemer le code de vérifications de ce type :

```
$canal = $order->get_meta( 'canal_origine' );
if ( empty( $canal ) ) {
    $canal = 'inconnu';
}
```

Cette ligne fonctionne, mais elle doit être recopiée dans chaque rapport, chaque export, chaque widget d'administration qui consulte cette méta. Le jour où la valeur par défaut change, il faut retrouver chaque occurrence.

## Déclarer une valeur par défaut avec register_meta()

> L'essentiel à retenir : register_meta() accepte un paramètre default depuis WordPress 5.5 ; La valeur par défaut ne s'applique qu'à get_metadata(), pas en base ; Elle évite de dupliquer des vérifications isset() partout dans le code

Depuis WordPress 5.5, la fonction `register_meta()` accepte un argument `default` dans son tableau d'arguments. Cette valeur est renvoyée par `get_metadata()`, et donc par `$order->get_meta()`, uniquement lorsque la méta n'existe pas du tout en base pour cet objet.

```
add_action( 'init', function () {
    register_meta( 'post', 'canal_origine', array(
        'type'         => 'string',
        'description'  => 'Canal ayant généré la commande',
        'single'       => true,
        'default'      => 'inconnu',
        'show_in_rest' => false,
    ) );
} );
```

Un point mérite d'être souligné : cette déclaration cible le type d'objet `post`, parce que les commandes WooCommerce restent stockées comme des articles tant que le stockage historique par table de commandes n'est pas activé sur le site concerné. Si ce mode alternatif est actif, la déclaration doit être adaptée au type d'objet correspondant fourni par WooCommerce.

## Ce que la valeur par défaut ne fait pas

Trois limites à connaître avant de considérer le problème résolu :

- La valeur par défaut n'écrit rien en base : elle n'apparaît que lors de la lecture, jamais dans une requête `WP_Query` ou `wc_get_orders()` filtrée sur cette méta.
- Une requête `meta_query` qui cherche `canal_origine = 'inconnu'` ne remontera donc jamais les anciennes commandes qui n'ont simplement pas la méta.
- La déclaration doit être exécutée avant toute lecture, généralement sur le hook `init`, sans quoi WordPress ne connaît pas encore la valeur par défaut au moment de l'appel.

## Migrer réellement les anciennes commandes

Pour les rapports qui doivent filtrer sur cette méta, la valeur par défaut ne suffit pas : il faut une migration ponctuelle qui écrit explicitement la valeur en base pour les commandes concernées.

```
$commandes = wc_get_orders( array(
    'limit'        => -1,
    'meta_key'     => 'canal_origine',
    'meta_compare' => 'NOT EXISTS',
) );

foreach ( $commandes as $commande ) {
    $commande->update_meta_data( 'canal_origine', 'inconnu' );
    $commande->save();
}
```

Sur un historique de plusieurs dizaines de milliers de commandes, ce script doit tourner par lots plutôt qu'en une seule exécution, pour rester compatible avec la limite de temps d'exécution PHP d'un hébergement mutualisé.

## Documenter la méta plutôt que la deviner

Un autre bénéfice de `register_meta()`, souvent sous-estimé, tient à l'argument `description` : il documente directement dans le code la signification de la méta, ce qui évite de la redécouvrir en lisant un connecteur tiers six mois plus tard. Sur un projet où plusieurs développeurs interviennent, je fais de cette déclaration un passage obligé dès qu'une nouvelle méta de commande est introduite.

> Je considère qu'une méta de commande sans `register_meta()` associé est une méta à moitié documentée : elle fonctionne, mais personne ne sait ce qu'elle contient sans relire tout l'historique du code.

## Pour aller plus loin

La valeur par défaut de `register_meta()` règle élégamment le problème de lecture, mais elle ne remplace pas une politique de migration pour les rapports qui filtrent sur la méta elle-même. Les deux mécanismes se complètent : l'un sécurise la lecture au quotidien, l'autre garantit que l'historique reste interrogeable pour des besoins statistiques plus poussés.

Sur un projet récent, cette double approche a évité de réécrire cinq rapports différents lors de l'ajout d'une nouvelle méta de canal d'origine : seule la déclaration a changé, et chaque rapport en a bénéficié sans modification.
