Skip to Content

Chapitre 7.4 — Métadonnées & metaboxes

⏱️ TL;DR — Les métadonnées (post_meta) attachent des données custom à un contenu (ISBN, prix, date d’un événement…). On les lit/écrit avec get_post_meta() / update_post_meta(). Deux façons de les éditer : les metaboxes classiques (un panneau PHP sur l’écran d’édition, avec nonce + sanitize + capability) ou, mieux à l’ère Gutenberg, les meta enregistrées (register_post_meta() avec show_in_rest) éditées via un panneau de bloc React (Partie 8). La règle de sécurité est omniprésente : vérifier le nonce, la capability, et assainir avant d’enregistrer.

🎯 Objectifs

  • Lire/écrire des métadonnées avec les fonctions dédiées.
  • Créer une metabox classique sécurisée (nonce, sanitize, capability).
  • Enregistrer une meta pour la REST/Gutenberg (register_post_meta).
  • Comprendre _underscore (meta protégée) et le pont vers le panneau bloc.

1. Lire et écrire une métadonnée

// Écrire update_post_meta( $post_id, 'wpr_isbn', '978-2-07-036002-4' ); // Lire (true = valeur unique, pas un tableau) $isbn = get_post_meta( $post_id, 'wpr_isbn', true ); // Supprimer delete_post_meta( $post_id, 'wpr_isbn' );
  • Stockées dans wp_postmeta (ch. 4.6), modèle clé/valeur.
  • Le 3ᵉ argument true de get_post_meta renvoie une valeur (sinon un tableau de toutes les valeurs de cette clé).

Convention _underscore : une clé commençant par _ (ex. _wpr_prix) est protégée — elle n’apparaît pas dans la métabox générique « Champs personnalisés » et n’est pas éditable directement par l’utilisateur. On l’utilise pour les meta gérées par le code (via metabox/bloc dédié).


2. Une metabox classique (sécurisée)

Trois étapes : ajouter la metabox, l’afficher, enregistrer ses données à save_post.

// 1) Ajouter la metabox add_action( 'add_meta_boxes', function () { add_meta_box( 'wpr_book_details', __( 'Détails du livre', 'wpr-books' ), 'wpr_book_details_html', 'livre', // écran (CPT) 'side' // contexte : side | normal | advanced ); } ); // 2) Afficher le champ (+ NONCE) function wpr_book_details_html( $post ) { wp_nonce_field( 'wpr_book_save', 'wpr_book_nonce' ); // ⚠️ jeton anti-CSRF $isbn = get_post_meta( $post->ID, '_wpr_isbn', true ); ?> <label for="wpr_isbn"><?php esc_html_e( 'ISBN', 'wpr-books' ); ?></label> <input type="text" id="wpr_isbn" name="wpr_isbn" value="<?php echo esc_attr( $isbn ); ?>" class="widefat" /> <?php } // 3) Enregistrer (nonce → capability → sanitize → update) add_action( 'save_post_livre', function ( $post_id ) { // a) Nonce (le formulaire vient bien de nous) if ( ! isset( $_POST['wpr_book_nonce'] ) || ! wp_verify_nonce( $_POST['wpr_book_nonce'], 'wpr_book_save' ) ) { return; } // b) Éviter l'autosave if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return; } // c) Capability (droit d'éditer CE contenu) if ( ! current_user_can( 'edit_post', $post_id ) ) { return; } // d) Sanitize AVANT d'enregistrer if ( isset( $_POST['wpr_isbn'] ) ) { update_post_meta( $post_id, '_wpr_isbn', sanitize_text_field( wp_unslash( $_POST['wpr_isbn'] ) ) ); } } );

⚠️ Piège critique — les 4 gardes de save_post. À l’enregistrement d’une metabox, il faut toujours : (1) vérifier le nonce (wp_verify_nonce), (2) ignorer l’autosave (DOING_AUTOSAVE), (3) vérifier la capability (current_user_can('edit_post', $id)), (4) assainir l’entrée (sanitize_* + wp_unslash). Oublier l’un de ces gardes est une faille classique (CSRF, injection, écrasement pendant l’autosave). C’est le patron à mémoriser (approfondi ch. 7.7).


3. L’approche moderne : register_post_meta + REST

Pour l’ère Gutenberg/headless, on enregistre la meta pour qu’elle soit exposée en REST et éditable via un panneau de bloc React (Partie 8) :

add_action( 'init', function () { register_post_meta( 'livre', 'wpr_isbn', array( 'type' => 'string', 'single' => true, 'show_in_rest' => true, // exposée dans /wp-json + éditable via @wordpress/data 'sanitize_callback' => 'sanitize_text_field', 'auth_callback' => function () { return current_user_can( 'edit_posts' ); }, ) ); } );

Avantages :

  • la meta apparaît dans la REST API (/wp/v2/livre/{id}meta.wpr_isbn) → headless direct (Partie 9) ;
  • elle est éditable proprement dans l’éditeur via @wordpress/data / useEntityProp (Partie 8), sans metabox PHP ;
  • sanitize_callback et auth_callback centralisent la sécurité.

⚠️ Piège — meta non exposée en REST. Une meta non enregistrée (register_post_meta) avec show_in_rest n’est pas visible dans la REST API (par défaut, les meta sont privées). Pour du headless ou un panneau bloc, enregistrez-la avec show_in_rest => true. Attention : n’exposez pas de meta sensible (données internes) en REST sans réfléchir.

💡 Pour un dev React — Deux mondes : la metabox classique (formulaire PHP + POST + save_post) est l’ancien modèle « form submit serveur ». register_post_meta + panneau bloc est le modèle moderne : la meta devient un champ d’API que votre composant React lit/écrit via un store (useEntityProp), avec sauvegarde AJAX transparente — exactement votre façon de gérer un champ contrôlé relié à une API. Pour un CPT destiné au headless, privilégiez cette voie.


4. Champs multiples et validation

  • Pour plusieurs champs, répétez le patron (un nonce par metabox suffit) ; assainissez chaque champ selon son type (sanitize_text_field, absint, sanitize_email, esc_url_raw…).
  • Pour de la validation métier (ISBN valide, prix positif), validez avant update_post_meta et signalez l’erreur (transient d’admin notice, ou côté bloc).
  • Pour des structures complexes (répétables), envisagez une table custom (ch. 5.6) ou un champ JSON — mais le plus souvent, post_meta suffit.

✏️ Exercices

  1. Citez les quatre vérifications obligatoires avant d’enregistrer une meta dans save_post.
  2. Vous développez un CPT destiné à être consommé par une app Next.js. Metabox classique ou register_post_meta ? Pourquoi ?
  3. Pourquoi préfixer certaines clés meta avec _ (underscore) ?

✅ Solution

  1. (1) Vérifier le nonce (wp_verify_nonce), (2) ignorer l’autosave (DOING_AUTOSAVE), (3) vérifier la capability (current_user_can('edit_post', $id)), (4) assainir l’entrée (sanitize_* + wp_unslash).
  2. register_post_meta avec show_in_rest => true : la meta est exposée dans la REST API (donc lisible/éditable par le front Next.js et par un panneau bloc React), avec sanitize/auth centralisés. Une metabox classique n’exposerait pas la donnée en REST.
  3. Le préfixe _ rend la meta protégée : elle n’apparaît pas dans la métabox générique « Champs personnalisés » et n’est pas éditable directement par l’utilisateur — réservée à une gestion par le code.

🧠 Quiz de révision

1. Quelles fonctions lisent/écrivent une métadonnée ?

get_post_meta() et update_post_meta() (+ delete_post_meta).

2. Que doit contenir une metabox pour être sûre à l’enregistrement ?

Un nonce (formulaire), et à save_post : vérif nonce + autosave + capability + sanitize.

3. Comment exposer une meta en REST / à Gutenberg ?

Avec register_post_meta() et show_in_rest => true (+ sanitize_callback, auth_callback).

4. Que signifie une clé meta commençant par _ ?

Une meta protégée, gérée par le code, invisible dans la métabox « Champs personnalisés ».

5. Pour un CPT headless, quelle approche de meta privilégier ?

register_post_meta avec show_in_rest (champ d’API éditable via @wordpress/data), plutôt qu’une metabox PHP.


Chapitre suivant : Settings API & pages d’administration.