Comment demander à quelqu’un qui n’a jamais ouvert un éditeur de blocs de mettre à jour son menu chaque matin, en moins de deux minutes, sans formation particulière ? C’est la question posée par un restaurateur dont l’unique contact avec un ordinateur se limitait à la caisse enregistreuse et à quelques e-mails.
La réponse retenue s’est éloignée des solutions habituelles à base de champs répétables ou de constructeur de blocs imbriqués : un simple champ de texte multiligne, dans lequel chaque ligne du menu suit un format strict, entrée-plat-dessert-prix, séparé par des points-virgules.
Un format de saisie volontairement simple
Le champ personnalisé attendu ressemble à ceci, saisi directement depuis un métabox classique sous l’éditeur :
Salade de saison; Poulet fermier, purée maison; Tarte du jour; 16,50
Velouté de légumes; Poisson du marché, riz; Fromage blanc; 17,00
Chaque ligne représente une formule complète. Le restaurateur n’a qu’à modifier ce texte chaque matin, sans naviguer entre plusieurs champs séparés ni comprendre la structure technique sous-jacente.
Enregistrer le champ et le rendre disponible au bloc
function restaurant_ajouter_metabox_menu() {
add_meta_box(
'restaurant_menu_jour',
'Menu du jour',
'restaurant_afficher_champ_menu',
'page',
'normal'
);
}
add_action( 'add_meta_boxes', 'restaurant_ajouter_metabox_menu' );
function restaurant_afficher_champ_menu( $post ) {
$valeur = get_post_meta( $post->ID, '_menu_du_jour_texte', true );
wp_nonce_field( 'restaurant_menu_nonce_action', 'restaurant_menu_nonce' );
echo '<textarea name="menu_du_jour_texte" rows="6" style="width:100%;">' . esc_textarea( $valeur ) . '</textarea>';
}

Analyser le texte côté rendu du bloc
Le render_callback du bloc découpe le texte ligne par ligne, puis champ par champ, avec une tolérance minimale aux espaces superflus :
function restaurant_rendre_bloc_menu( $attributs, $contenu, $bloc ) {
$page_id = $bloc->context['postId'] ?? get_the_ID();
$texte_brut = get_post_meta( $page_id, '_menu_du_jour_texte', true );
if ( empty( $texte_brut ) ) {
return '<p>Le menu du jour n\'a pas encore été mis à jour.</p>';
}
$lignes = array_filter( array_map( 'trim', explode( "\n", $texte_brut ) ) );
$sortie = '<ul>';
foreach ( $lignes as $ligne ) {
$champs = array_map( 'trim', explode( ';', $ligne ) );
if ( count( $champs ) !== 4 ) {
continue;
}
list( $entree, $plat, $dessert, $prix ) = $champs;
$sortie .= sprintf(
'<li>%s — %s — %s (%s €)</li>',
esc_html( $entree ), esc_html( $plat ), esc_html( $dessert ), esc_html( $prix )
);
}
return $sortie . '</ul>';
}
Que se passe-t-il quand le format n’est pas respecté
Un restaurateur pressé peut oublier un point-virgule, ou coller un texte copié depuis un autre document avec une mise en forme différente. Le choix a été de simplement ignorer silencieusement les lignes mal formées plutôt que d’afficher une erreur technique incompréhensible pour l’utilisateur final. Une ligne d’aide reste affichée en permanence au-dessus du champ de saisie, dans l’administration :
- « Une ligne par formule, dans l’ordre : entrée ; plat ; dessert ; prix » ;
- « Séparez chaque élément par un point-virgule » ;
- « Le prix ne doit contenir que des chiffres et une virgule ».
Pourquoi ne pas utiliser des champs répétables
Une interface avec un bouton « ajouter une formule » et des champs séparés pour chaque élément aurait été plus rigoureuse techniquement, mais plus intimidante visuellement pour un public peu technophile. Le compromis retenu privilégie la vitesse de saisie quotidienne sur la rigueur de structuration des données, un choix assumé compte tenu du profil de l’utilisateur final.
Le meilleur outil de saisie n’est pas le plus structuré techniquement : c’est celui que la personne qui l’utilise chaque jour comprend du premier coup d’œil.
En résumé
Pour un restaurateur qui doit mettre à jour son menu chaque matin sans formation technique, un simple champ de texte multiligne, analysé par un bloc dynamique tolérant aux petites imperfections de saisie, s’est révélé plus adapté qu’une interface de champs répétables plus rigoureuse mais plus complexe à utiliser au quotidien. La réservation de table reste hors du périmètre de ce bloc, gérée par un service tiers déjà en place.