vendredi 25 septembre 2026

À propos

Contact

Blocs Gutenberg

Le piège du save() qui retourne null : contenu perdu à la désactivation

Désactiver un plugin fournisseur de blocs ne devrait jamais faire disparaître du contenu déjà publié. Sauf quand save() a été écrit trop vite.

Par Clément Hadrot • 1 octobre 2020 • 5 min de lecture • Aucun commentaire
Le piège du save() qui retourne null : contenu perdu à la désactivation

Un client avait temporairement désactivé une extension pour isoler un conflit suspecté avec une mise à jour de thème. Le conflit ne venait pas de là, mais la désactivation a suffi à faire disparaître l’intégralité d’un bloc d’horaires d’ouverture présent sur toutes les pages du site, remplacé par un message « ce bloc contient une erreur non prise en charge ». Une fois l’extension réactivée, le contenu est réapparu comme si de rien n’était, ce qui a semé une confusion légitime : comment un simple aller-retour de désactivation peut-il faire disparaître, puis réapparaître, du contenu sans qu’aucune donnée n’ait été modifiée en base ?

La réponse tient dans un choix d’implémentation très répandu chez les blocs entièrement dynamiques : une fonction save() qui retourne null, combinée à l’absence de tout filet de sécurité côté rendu. Comprendre ce mécanisme évite de reproduire ce piège sur ses propres blocs, en particulier ceux dont le rendu dépend intégralement de PHP.

Ce que save() décide vraiment

La fonction save() ne définit pas ce qui s’affiche sur le site public : elle définit ce qui est écrit dans post_content, entre les delimiters de bloc, au moment où l’article est enregistré. Pour un bloc entièrement dynamique, dont l’affichage réel dépend d’un render_callback PHP exécuté à chaque chargement de page, il est courant — et recommandé par la documentation officielle — de faire retourner null à save(), puisque le contenu final n’a de toute façon aucun rapport avec ce qui serait figé côté JavaScript.

registerBlockType( 'mon-agence/horaires', {
    edit: EditComponent,
    save: () => null,
} );

Le problème apparaît quand le plugin disparaît

Ce choix fonctionne parfaitement tant que l’extension qui fournit le render_callback reste active : à chaque affichage, WordPress appelle la fonction PHP enregistrée et injecte son retour à la place du bloc. Mais dès que l’extension est désactivée, ce callback n’existe plus. WordPress ne dispose alors, dans post_content, que du delimiter de bloc et de son JSON d’attributs, puisque save() a justement choisi de n’y écrire aucun HTML de secours.

Résultat : sans callback disponible pour interpréter ces attributs, WordPress affiche le contenu tel quel, c’est-à-dire rien de visible pour le visiteur, ou un message d’erreur générique dans l’éditeur au retour du rédacteur.

Le filet de sécurité oublié

La parade existe et elle est documentée, mais fréquemment oubliée dans l’urgence d’un développement : ajouter un contenu de repli dans save(), ou a minima s’assurer que le render_callback gère lui-même le cas d’attributs incomplets. Une approche simple consiste à faire retourner à save() un balisage minimal statique plutôt que null, qui reste lisible même sans le PHP qui l’enrichirait normalement.

L'essentiel à retenir : save() détermine ce qui reste en base sans le plugin ; null oblige à passer par render_callback ; Sans les deux, le contenu disparaît purement et simplement
save: ( { attributes } ) => {
    const { ville, adresse } = attributes;
    return (
        <div>
            <p>{ ville }</p>
            <p>{ adresse }</p>
        </div>
    );
},

Ce n’est pas la version enrichie que le visiteur verrait normalement (avec calcul de l’état ouvert ou fermé selon l’heure, par exemple), mais c’est suffisant pour qu’une information basique reste visible même si le plugin est désactivé, mis à jour de façon incompatible, ou tout simplement supprimé par erreur.

Une checklist avant de choisir null

  • Le contenu du bloc a-t-il une valeur informative suffisante sans le calcul dynamique du serveur ?
  • Un rédacteur ou un client final comprendrait-il pourquoi le contenu disparaît en cas de désactivation ?
  • Existe-t-il un scénario réaliste où l’extension serait désactivée temporairement (maintenance, débogage, migration) ?

Si la réponse à la troisième question est oui, ce qui concerne la quasi-totalité des sites en production, un retour null pur mérite d’être reconsidéré au profit d’un contenu de repli, même minimal.

Comment détecter ce piège avant qu’un client ne le découvre

Le test le plus fiable reste le plus simple : désactiver volontairement l’extension sur un environnement de recette et vérifier ce qui reste affiché sur les pages qui contiennent le bloc concerné. C’est un test rarement inclus dans une checklist de recette classique, qui se concentre en général sur le fonctionnement de l’extension active plutôt que sur son absence.

Un bon bloc dynamique devrait pouvoir survivre, même dégradé, à la désactivation de son propre plugin. Un bloc qui disparaît totalement n’est jamais un choix assumé, c’est presque toujours un oubli.

En résumé

Le retour null dans save() est une pratique légitime pour les blocs dynamiques, recommandée par la documentation officielle elle-même, mais elle déplace toute la responsabilité de l’affichage vers le PHP côté serveur. Sans un contenu de repli minimal, la moindre désactivation, même temporaire et involontaire, transforme un bloc fonctionnel en trou noir de contenu. Un test systématique de désactivation avant mise en production permet d’éviter cette mauvaise surprise, bien plus tard, chez le client.

Partager :

À propos de l'auteur

Clément Hadrot

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi