# Un menu de saison en JSON, stocké dans un champ personnalisé de thème

> Stocker un menu du jour en JSON dans un champ personnalisé et le restituer proprement dans le template, pour un restaurateur sans compétence technique.

- Auteur : WordPress Développement
- Publié le : 2023-07-12
- Mis à jour le : 2023-07-12
- Catégorie : Thèmes
- URL : https://www.wpmoderne.fr/themes/menu-saison-json-champ-personnalise-theme-restaurant/

## L’essentiel

- Une seule zone de texte pour tout le menu, format JSON validé
- Interface de saisie simplifiée avec exemple pré-rempli
- Rendu conditionnel selon la présence de chaque section

Comment un restaurateur qui ne connaît rien au code peut-il mettre à jour son menu du jour sans appeler son développeur chaque matin ? La réponse retenue sur ce projet a surpris le client autant que moi au départ : un simple champ de texte contenant du JSON, plutôt qu'une interface de champs multiples ou une extension de gestion de menu dédiée.

Ce choix, qui peut sembler contre-intuitif pour un client non technique, s'est révélé plus simple à maintenir et à faire évoluer qu'une solution avec des dizaines de petits champs. Voici pourquoi, et comment l'interface de saisie a été pensée pour rester accessible malgré le format brut.

## Pourquoi le JSON plutôt qu'une multitude de petits champs

Un menu du jour varie en nombre de plats selon la saison : parfois trois entrées, parfois une seule ; parfois un menu enfant, parfois non. Une interface à champs fixes (entrée 1, entrée 2, entrée 3…) aurait soit limité artificiellement le nombre de plats, soit multiplié les champs vides à ignorer. Le JSON, stocké dans une unique métadonnée de type de contenu `menu_jour`, s'adapte naturellement à cette variabilité.

```
{
    "entrees": ["Velouté de courge", "Terrine maison"],
    "plats": ["Filet de bar, légumes de saison", "Risotto aux champignons"],
    "desserts": ["Tarte fine aux pommes"],
    "menu_enfant": true
}
```

> L'essentiel à retenir : Une seule zone de texte pour tout le menu, format JSON validé ; Interface de saisie simplifiée avec exemple pré-rempli ; Rendu conditionnel selon la présence de chaque section

## Une interface de saisie qui masque la complexité du format

Demander au restaurateur de taper du JSON à la main directement dans l'administration aurait été voué à l'échec dès la première faute de virgule. La boîte méta ajoutée au type de contenu `menu_jour` propose donc une zone de texte pré-remplie avec un exemple complet et commenté, accompagnée d'un texte d'aide rappelant la structure attendue.

```
add_action( 'add_meta_boxes', function () {
    add_meta_box(
        'menu_json',
        'Menu du jour (format JSON)',
        function ( $post ) {
            $valeur = get_post_meta( $post->ID, 'menu_json', true );
            printf(
                '<textarea name="menu_json" rows="10" style="width:100%%">%s</textarea><p>Respectez le format de l\'exemple fourni.</p>',
                esc_textarea( $valeur )
            );
        },
        'menu_jour'
    );
} );
```

## Valider le JSON avant l'enregistrement

À l'enregistrement, une vérification avec `json_decode()` et un contrôle de l'erreur via `json_last_error()` empêche l'enregistrement d'un menu mal formé, avec un message d'erreur explicite plutôt qu'un plantage silencieux à l'affichage.

```
add_action( 'save_post_menu_jour', function ( $post_id ) {
    if ( ! isset( $_POST['menu_json'] ) ) {
        return;
    }

    $donnees = json_decode( wp_unslash( $_POST['menu_json'] ), true );

    if ( JSON_ERROR_NONE !== json_last_error() ) {
        add_settings_error( 'menu_json', 'json_invalide', 'Le format JSON du menu est invalide, l\'ancien menu a été conservé.' );
        return;
    }

    update_post_meta( $post_id, 'menu_json', wp_unslash( $_POST['menu_json'] ) );
} );
```

## Un rendu conditionnel section par section

Côté affichage, chaque section (entrées, plats, desserts, menu enfant) n'apparaît que si elle est renseignée dans le JSON, évitant un titre de section vide certains jours où le restaurateur ne propose pas d'entrée par exemple.

- Décodage du JSON avec `json_decode( $valeur, true )` au moment de l'affichage, jamais en base.
- Une boucle `foreach` par section, ignorée si le tableau correspondant est vide ou absent.
- Le menu enfant affiché uniquement si la clé `menu_enfant` vaut `true`.

## Le point qui a le plus rassuré le client

Contrairement à une crainte initiale, le restaurateur a rapidement pris l'habitude de dupliquer le menu de la veille dans un éditeur de texte classique et de modifier seulement les plats qui changent, plutôt que de repartir de zéro chaque jour. L'exemple pré-rempli dans l'aide contextuelle sert alors surtout de filet de sécurité en cas de doute sur la syntaxe.

> Un format technique comme le JSON peut tout à fait convenir à un utilisateur non technique, à condition de soigner l'aide contextuelle et de valider strictement avant l'enregistrement : c'est la marge d'erreur qui doit être réduite, pas nécessairement la complexité apparente du champ.

## En résumé

Ce champ JSON unique a remplacé ce qui aurait pu devenir une dizaine de petits champs répétitifs, tout en s'adaptant naturellement à un menu qui varie en nombre de plats selon les jours. La clé du succès n'était pas de simplifier le format de stockage, mais de rendre la validation et l'aide à la saisie suffisamment robustes pour qu'un restaurateur sans compétence technique s'en empare sans crainte.
