Chapitre 10.3 — Personnaliser produits & checkout
⏱️ TL;DR — Deux besoins fréquents : enrichir les produits (champ custom, onglet, données affichées) et adapter le checkout (ajouter/retirer/valider des champs, conditions). Côté produit : on ajoute des champs dans l’admin (
woocommerce_product_options_*+save_post) et on les affiche via hooks. Côté checkout : historiquement les hookswoocommerce_checkout_fields, mais le checkout est désormais en blocs (Gutenberg) — la personnalisation moderne passe par des blocs/inner blocks et l’API des champs additionnels. On sécurise toujours (sanitize/escape/nonce, ch. 7.7).
🎯 Objectifs
- Ajouter un champ custom à un produit (admin + affichage).
- Personnaliser les champs du checkout (classique et blocs).
- Valider et sécuriser les données saisies.
- Connaître la bascule checkout classique → checkout blocs.
1. Ajouter un champ custom à un produit
Dans l’admin produit, on ajoute un champ dans un groupe d’options, puis on l’enregistre (mêmes réflexes que les metaboxes, ch. 7.4) :
// Afficher un champ dans l'onglet "Général"
add_action( 'woocommerce_product_options_general_product_data', function () {
woocommerce_wp_text_input( array(
'id' => '_wpr_isbn',
'label' => __( 'ISBN', 'wpr' ),
'desc_tip' => true,
) );
} );
// Enregistrer (Woo fournit un hook dédié à la sauvegarde produit)
add_action( 'woocommerce_admin_process_product_object', function ( $product ) {
if ( isset( $_POST['_wpr_isbn'] ) ) {
$product->update_meta_data( '_wpr_isbn', sanitize_text_field( wp_unslash( $_POST['_wpr_isbn'] ) ) );
}
} );woocommerce_wp_text_input()(et_select,_checkbox…) génèrent des champs cohérents avec l’UI Woo.woocommerce_admin_process_product_objectreçoit l’objetWC_Product: on met à jour viaupdate_meta_data+ lesaveest géré par Woo (pas deupdate_post_metaen dur, ch. 10.1).- Sanitize l’entrée (Woo gère le nonce du formulaire produit, mais on assainit toujours).
Afficher le champ sur la fiche produit : via un hook de template (ch. 10.2) et $product->get_meta( '_wpr_isbn' ), en échappant la sortie.
2. Un onglet produit custom
add_filter( 'woocommerce_product_tabs', function ( $tabs ) {
$tabs['wpr_infos'] = array(
'title' => __( 'Fiche technique', 'wpr' ),
'priority' => 25,
'callback' => function () {
global $product;
echo '<p>' . esc_html( $product->get_meta( '_wpr_isbn' ) ) . '</p>';
},
);
return $tabs;
} );Un filtre ajoute un onglet à la fiche produit (Description, Avis… + le vôtre).
3. Personnaliser le checkout (classique)
Historiquement, les champs du checkout se modifient via le filtre woocommerce_checkout_fields :
add_filter( 'woocommerce_checkout_fields', function ( $fields ) {
$fields['billing']['billing_company']['required'] = false; // rendre optionnel
$fields['order']['wpr_instructions'] = array( // ajouter un champ
'type' => 'textarea',
'label' => __( 'Instructions de livraison', 'wpr' ),
'required' => false,
);
return $fields;
} );
// Enregistrer le champ custom sur la commande
add_action( 'woocommerce_checkout_update_order_meta', function ( $order_id ) {
if ( ! empty( $_POST['wpr_instructions'] ) ) {
$order = wc_get_order( $order_id );
$order->update_meta_data( '_wpr_instructions', sanitize_textarea_field( wp_unslash( $_POST['wpr_instructions'] ) ) );
$order->save();
}
} );Validation custom via woocommerce_checkout_process (ajouter une wc_add_notice( …, 'error' ) pour bloquer).
4. Le checkout en blocs (moderne)
WooCommerce a introduit un checkout basé sur des blocs (Gutenberg) qui remplace progressivement le checkout « shortcode ». Conséquence majeure :
⚠️ Piège n°1 —
woocommerce_checkout_fieldsignoré par le checkout blocs. Le filtre classique ne s’applique pas au checkout en blocs. Pour ce dernier, on utilise l’API des champs additionnels (woocommerce_register_additional_checkout_field) et/ou des blocs d’extension (inner blocks du checkout). Vérifiez quel checkout la boutique utilise (shortcode legacy vs blocs) avant de coder — c’est la confusion n°1 aujourd’hui.
Exemple (checkout blocs) — champ additionnel via l’API récente :
add_action( 'woocommerce_init', function () {
woocommerce_register_additional_checkout_field( array(
'id' => 'wpr/instructions',
'label' => __( 'Instructions de livraison', 'wpr' ),
'location' => 'order',
'type' => 'text',
) );
} );Cette API expose le champ dans le checkout blocs et le stocke proprement sur la commande. L’écosystème évolue vite : consultez la doc à jour pour la signature exacte.
5. Sécurité et bonnes pratiques
- Sanitize toute entrée (checkout, admin produit), échappez l’affichage (ch. 7.7).
- Passez par les objets (
$product,$order) et leurs méthodes, pas le SQL/meta direct (ch. 10.1). - Préférez les hooks/API à la surcharge de template (ch. 10.2).
- Testez sur le checkout réel de la boutique (blocs vs classique).
💡 Pour un dev React — Le passage au checkout en blocs rapproche WooCommerce de votre monde : le checkout devient une app React (
@woocommerce/blocks), extensible par des composants/inner blocks et une API de champs — plus par des filtres PHP. Pour des personnalisations riches du checkout moderne, vos compétences React (Partie 8) redeviennent l’atout. C’est un créneau technique peu pourvu (beaucoup de devs Woo « classiques » sont à l’aise en PHP mais pas en React).
✏️ Exercices
- Vous ajoutez un champ « ISBN » à un produit. Quels hooks pour l’afficher en admin et l’enregistrer proprement ?
- Pourquoi votre
woocommerce_checkout_fieldsn’a-t-il aucun effet sur une boutique récente ? - Où enregistre-t-on un champ custom saisi au checkout (classique) sur la commande ?
✅ Solution
- Afficher :
woocommerce_product_options_general_product_dataavecwoocommerce_wp_text_input. Enregistrer :woocommerce_admin_process_product_object(reçoitWC_Product) →update_meta_data+sanitize_text_field. On passe par l’objet produit, pasupdate_post_metaen dur. - Parce que la boutique utilise le checkout en blocs, sur lequel le filtre
woocommerce_checkout_fields(checkout classique) ne s’applique pas. Il faut l’API des champs additionnels (woocommerce_register_additional_checkout_field) ou des blocs d’extension. - Sur le hook
woocommerce_checkout_update_order_meta: récupérer la commande (wc_get_order),update_meta_dataavec la valeur assainie,save().
🧠 Quiz de révision
1. Quel hook enregistre un champ produit custom proprement ?
woocommerce_admin_process_product_object (via l’objet WC_Product + update_meta_data).
2. Comment ajoute-t-on un onglet à la fiche produit ?
Via le filtre woocommerce_product_tabs (titre, priorité, callback).
3. Le filtre woocommerce_checkout_fields marche-t-il partout ?
Non : pas sur le checkout en blocs ; il faut alors l’API des champs additionnels / blocs d’extension.
4. Comment valider une saisie au checkout (classique) ?
Via woocommerce_checkout_process en ajoutant une wc_add_notice(…, 'error') pour bloquer.
5. Pourquoi le checkout blocs est-il un atout pour un dev React ?
Il est en React (@woocommerce/blocks) : la personnalisation riche passe par des composants/blocs — un créneau peu pourvu chez les devs Woo classiques.
Chapitre suivant : Développer une extension WooCommerce.