Un bloc Gutenberg statique suffit pour une citation, une grille simple ou un encart éditorial. Mais dès que le contenu dépend de WordPress, d’une option, d’une requête, d’un rôle utilisateur ou d’une donnée métier, le rendu côté serveur redevient très utile. Le bloc reste manipulable dans l’éditeur, mais son HTML final est généré en PHP au moment de l’affichage.
Dans ce tutoriel, on va créer un bloc dynamique très simple : une carte de maintenance qui affiche un titre, un statut et un message. Ce n’est pas un gadget. Le même principe sert pour afficher des articles récents, un prix WooCommerce, un état de disponibilité, une donnée ACF, une alerte client ou un contenu conditionnel. L’objectif est d’avoir une base propre, moderne, sécurisée et facile à étendre.
Structure du plugin
On part sur un petit plugin dédié. C’est plus propre que de mettre le bloc dans le thème, surtout si le contenu doit survivre à une refonte graphique.
wp-content/plugins/wpalab-maintenance-card/
├── wpalab-maintenance-card.php
└── blocks/
└── maintenance-card/
├── block.json
├── editor.js
├── style.css
└── render.php
Créez les dossiers, puis ajoutez le fichier principal du plugin.
<?php
/**
* Plugin Name: WPAdminLab Maintenance Card
* Description: Bloc Gutenberg dynamique rendu côté serveur.
* Version: 1.0.0
* Author: WPAdminLab
*/
if (! defined('ABSPATH')) {
exit;
}
add_action('init', function () {
register_block_type(__DIR__ . '/blocks/maintenance-card');
});
La fonction register_block_type() lit automatiquement le fichier block.json. C’est le standard à privilégier aujourd’hui : moins de code PHP répétitif, meilleure compatibilité avec l’éditeur, et une déclaration claire des assets.
Déclarer le bloc avec block.json
Dans blocks/maintenance-card/block.json, ajoutez :
{
"apiVersion": 3,
"name": "wpalab/maintenance-card",
"title": "Maintenance Card",
"category": "widgets",
"icon": "admin-tools",
"description": "Affiche une carte de statut de maintenance.",
"textdomain": "wpalab",
"attributes": {
"title": {
"type": "string",
"default": "Maintenance WordPress"
},
"status": {
"type": "string",
"default": "ok"
},
"message": {
"type": "string",
"default": "Le site est surveillé et à jour."
}
},
"editorScript": "file:./editor.js",
"style": "file:./style.css",
"render": "file:./render.php"
}
Trois points comptent ici. D’abord, apiVersion: 3 indique un bloc moderne. Ensuite, les attributs définissent ce que l’éditeur stocke dans le contenu. Enfin, la propriété render pointe vers le fichier PHP chargé de produire le HTML public.
Créer l’interface dans l’éditeur
Pour rester léger, on utilise les dépendances WordPress globales. Dans un projet plus gros, vous passerez par @wordpress/scripts et une vraie étape de build. Pour ce bloc simple, ce fichier suffit.
(function (blocks, element, blockEditor, components) {
const el = element.createElement;
const useBlockProps = blockEditor.useBlockProps;
const InspectorControls = blockEditor.InspectorControls;
const TextControl = components.TextControl;
const SelectControl = components.SelectControl;
const PanelBody = components.PanelBody;
blocks.registerBlockType('wpalab/maintenance-card', {
edit: function (props) {
const attrs = props.attributes;
const setAttributes = props.setAttributes;
const blockProps = useBlockProps({ className: 'wpalab-maintenance-card' });
return el(
'div',
blockProps,
el(InspectorControls, null,
el(PanelBody, { title: 'Réglages', initialOpen: true },
el(TextControl, {
label: 'Titre',
value: attrs.title,
onChange: function (value) { setAttributes({ title: value }); }
}),
el(SelectControl, {
label: 'Statut',
value: attrs.status,
options: [
{ label: 'OK', value: 'ok' },
{ label: 'Attention', value: 'warning' },
{ label: 'Critique', value: 'critical' }
],
onChange: function (value) { setAttributes({ status: value }); }
}),
el(TextControl, {
label: 'Message',
value: attrs.message,
onChange: function (value) { setAttributes({ message: value }); }
})
)
),
el('strong', null, attrs.title),
el('p', null, attrs.message)
);
},
save: function () {
return null;
}
});
})(window.wp.blocks, window.wp.element, window.wp.blockEditor, window.wp.components);
Le save retourne null parce que le HTML n’est pas sauvegardé en dur dans le post. WordPress conserve les attributs du bloc, puis appelle le rendu PHP en front. C’est exactement ce qu’on veut pour un bloc dynamique.
Rendre le HTML en PHP
Dans render.php, on récupère les attributs, on les nettoie, puis on génère un markup simple.
<?php
if (! defined('ABSPATH')) {
exit;
}
$title = isset($attributes['title']) ? sanitize_text_field($attributes['title']) : '';
$message = isset($attributes['message']) ? sanitize_text_field($attributes['message']) : '';
$status = isset($attributes['status']) ? sanitize_key($attributes['status']) : 'ok';
$allowed_statuses = array('ok', 'warning', 'critical');
if (! in_array($status, $allowed_statuses, true)) {
$status = 'ok';
}
$label = array(
'ok' => 'OK',
'warning' => 'Attention',
'critical' => 'Critique',
)[$status];
?>
<div <?php echo get_block_wrapper_attributes(array(
'class' => 'wpalab-maintenance-card is-' . esc_attr($status),
)); ?>>
<span class="wpalab-maintenance-card__status"><?php echo esc_html($label); ?></span>
<h2 class="wpalab-maintenance-card__title"><?php echo esc_html($title); ?></h2>
<p class="wpalab-maintenance-card__message"><?php echo esc_html($message); ?></p>
</div>
La partie importante n’est pas la carte, c’est l’hygiène. On nettoie avec sanitize_text_field() et sanitize_key(), puis on échappe à la sortie avec esc_html() et esc_attr(). En WordPress, la règle est simple : valider à l’entrée, échapper à la sortie, même si la donnée vient de l’éditeur.
Ajouter un minimum de style
Dans style.css, gardez une base sobre et lisible :
.wpalab-maintenance-card {
border: 1px solid #d8dee4;
border-left-width: 6px;
border-radius: 8px;
padding: 1rem;
background: #ffffff;
}
.wpalab-maintenance-card.is-ok { border-left-color: #1f883d; }
.wpalab-maintenance-card.is-warning { border-left-color: #bf8700; }
.wpalab-maintenance-card.is-critical { border-left-color: #cf222e; }
.wpalab-maintenance-card__status {
display: inline-block;
margin-bottom: .5rem;
font-size: .75rem;
font-weight: 700;
text-transform: uppercase;
}
.wpalab-maintenance-card__title {
margin: 0 0 .5rem;
font-size: 1.25rem;
}
.wpalab-maintenance-card__message {
margin: 0;
}
Tester le bloc
Activez le plugin, ouvrez un article, insérez le bloc Maintenance Card, modifiez les champs puis prévisualisez. Si le bloc n’apparaît pas, vérifiez d’abord que le plugin est actif et que le chemin déclaré dans register_block_type() pointe bien vers le dossier contenant block.json.
wp plugin activate wpalab-maintenance-card
wp plugin list --status=active --format=table
Pour diagnostiquer une erreur PHP, activez temporairement les logs en staging :
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
Comment l’étendre proprement
Une fois cette base en place, vous pouvez remplacer le message manuel par une donnée dynamique : option WordPress, transient, requête REST, dernier rapport de sauvegarde, statut WooCommerce ou résultat d’un contrôle de maintenance. La règle reste la même : le bloc stocke des paramètres, le PHP calcule le rendu final.
Évitez de transformer le bloc en usine à tout faire. Si vous avez trois usages très différents, créez trois blocs. Un bloc clair, avec peu d’attributs, sera plus facile à maintenir qu’un composant géant rempli de conditions.
Conclusion
Le rendu côté serveur n’est pas un retour en arrière. C’est une technique moderne quand le contenu dépend de WordPress au moment de l’affichage. Avec block.json, un fichier render.php et quelques garde-fous de sécurité, vous obtenez un bloc robuste, compatible avec l’éditeur, et adapté aux vrais besoins métier.
Commentaires (0)
Laisser un commentaire
Les commentaires sont modérés. Questions WordPress, cybersécurité ou dev web bienvenues.