# Customizer API : ajouter panneaux, sections et contrôles à un thème classique

> Tutoriel complet sur $wp_customize, sanitize_callback et l'aperçu live par postMessage pour construire un panneau de réglages solide.

- Auteur : Clément Hadrot
- Publié le : 2020-05-20
- Mis à jour le : 2020-05-20
- Catégorie : Thèmes
- URL : https://wpmoderne.dev.wordpress-developpement.fr/themes/customizer-api-panneaux-sections/

## L’essentiel

- add_panel et add_section pour organiser les réglages
- sanitize_callback systématique sur chaque setting
- postMessage pour un aperçu instantané

Pour la Brasserie du Lavoir, le thème sur mesure devait permettre à la gérante de changer elle-même la couleur d'accent, le texte d'accroche de la page d'accueil et le numéro de téléphone affiché dans l'en-tête, sans toucher au code. Plutôt que d'installer un constructeur de page complet pour trois réglages, l'API Customizer de WordPress suffisait largement — à condition de bien structurer panneaux, sections et contrôles.

Ce tutoriel construit, étape par étape, un panneau de réglages complet avec `$wp_customize`, en insistant sur deux points souvent négligés : la validation systématique des valeurs saisies, et l'aperçu live par `postMessage` pour éviter à l'utilisateur d'attendre un rechargement à chaque modification.

## Organiser un panneau et ses sections

Tout commence par le crochet `customize_register`, qui reçoit l'instance de `WP_Customize_Manager`. On y crée d'abord un panneau dédié, puis des sections à l'intérieur :

```
function agence_customize_register( $wp_customize ) {
	$wp_customize->add_panel( 'agence_panel', array(
		'title'    => __( 'Réglages Brasserie du Lavoir', 'agence' ),
		'priority' => 30,
	) );

	$wp_customize->add_section( 'agence_section_header', array(
		'title' => __( 'En-tête du site', 'agence' ),
		'panel' => 'agence_panel',
	) );

	$wp_customize->add_section( 'agence_section_colors', array(
		'title' => __( 'Couleurs', 'agence' ),
		'panel' => 'agence_panel',
	) );
}
add_action( 'customize_register', 'agence_customize_register' );
```

Regrouper les réglages dans un panneau nommé selon le projet, plutôt que de les disperser dans les sections génériques déjà présentes, évite à l'utilisateur final de chercher ses options au milieu de celles fournies par le thème parent ou par des extensions.

## Un setting, un contrôle, un sanitize_callback

> L'essentiel à retenir : add_panel et add_section pour organiser les réglages ; sanitize_callback systématique sur chaque setting ; postMessage pour un aperçu instantané

Chaque réglage se déclare en deux temps : le `setting`, qui stocke la valeur en base, et le `control`, qui affiche le champ dans l'interface. Le paramètre `sanitize_callback` n'est pas optionnel dans une implémentation sérieuse : sans lui, n'importe quelle valeur, y compris du code malveillant, peut être enregistrée telle quelle.

```
$wp_customize->add_setting( 'agence_phone_number', array(
	'default'           => '02 40 00 00 00',
	'sanitize_callback' => 'sanitize_text_field',
	'transport'         => 'postMessage',
) );

$wp_customize->add_control( 'agence_phone_number', array(
	'label'   => __( 'Numéro affiché en en-tête', 'agence' ),
	'section' => 'agence_section_header',
	'type'    => 'text',
) );

$wp_customize->add_setting( 'agence_accent_color', array(
	'default'           => '#c1440e',
	'sanitize_callback' => 'sanitize_hex_color',
	'transport'         => 'postMessage',
) );

$wp_customize->add_control( new WP_Customize_Color_Control(
	$wp_customize,
	'agence_accent_color',
	array(
		'label'   => __( 'Couleur d\'accent', 'agence' ),
		'section' => 'agence_section_colors',
	)
) );
```

Le choix du `sanitize_callback` dépend toujours de la nature de la donnée : `sanitize_text_field` pour du texte simple, `sanitize_hex_color` pour une couleur, `absint` pour un entier positif, `esc_url_raw` pour une URL. Utiliser systématiquement `sanitize_text_field` par facilité, y compris sur un champ URL, laisse passer des valeurs qui ne se comporteront pas comme prévu à l'affichage.

## L'aperçu live sans rechargement de page

Par défaut, sans précision de `transport`, chaque modification dans le Customizer recharge entièrement l'aperçu — lent et frustrant dès qu'on ajuste une couleur par petites touches. En passant `'transport' => 'postMessage'` sur le setting, puis en écoutant les changements côté JavaScript, l'aperçu se met à jour instantanément :

```
( function( $ ) {
	wp.customize( 'agence_phone_number', function( value ) {
		value.bind( function( newValue ) {
			$( '.site-header .phone-number' ).text( newValue );
		} );
	} );

	wp.customize( 'agence_accent_color', function( value ) {
		value.bind( function( newValue ) {
			document.documentElement.style.setProperty( '--accent-color', newValue );
		} );
	} );
} )( jQuery );
```

Ce fichier JavaScript doit être enregistré via `customize_preview_init`, un crochet distinct de `customize_register`, sans quoi il ne sera jamais chargé dans le contexte de l'aperçu :

```
function agence_customize_preview_js() {
	wp_enqueue_script(
		'agence-customizer-preview',
		get_theme_file_uri( 'assets/js/customizer-preview.js' ),
		array( 'customize-preview', 'jquery' ),
		'1.0',
		true
	);
}
add_action( 'customize_preview_init', 'agence_customize_preview_js' );
```

### Lire les valeurs côté template

Une fois les réglages enregistrés, il ne reste qu'à les lire avec `get_theme_mod()` dans les gabarits du thème, en fournissant toujours une valeur par défaut cohérente avec celle déclarée dans le setting :

- `get_theme_mod( 'agence_phone_number', '02 40 00 00 00' )` dans `header.php`.
- `get_theme_mod( 'agence_accent_color', '#c1440e' )` injecté en CSS inline via `wp_add_inline_style()`.

> Un sanitize_callback absent n'est jamais un oubli sans conséquence : c'est une porte ouverte qui finit toujours par être trouvée, tôt ou tard.

## Pour aller plus loin

Cette base — panneaux, sections, sanitize_callback rigoureux et postMessage — couvre l'essentiel des besoins d'un thème sur mesure en 2020. Sur des projets plus ambitieux, on pourra explorer les `Customize_Partial` pour un rafraîchissement sélectif de zones entières sans JavaScript personnalisé. Ce sera l'objet d'un prochain article, une fois quelques projets supplémentaires livrés avec cette approche.
