Pendant des années, la maîtrise du développement de blocs Gutenberg exigeait une connaissance approfondie de technologies telles que React et Node.js, ainsi que des étapes de compilation complexes et l’utilisation d’outils JavaScript.
Cependant, le développement WordPress évolue, et il est désormais possible de créer et de gérer des blocs Gutenberg entièrement en PHP.
Cela est particulièrement avantageux pour les développeurs qui préfèrent éviter React et le développement JavaScript (JS) côté serveur. Cela réduit la courbe d’apprentissage, simplifie l’expérience du développeur et permet d’obtenir de meilleures performances en supprimant la surcharge inutile des scripts front-end.
Dans les sections suivantes, vous apprendrez à tirer parti de ces nouvelles fonctionnalités pour créer des blocs Gutenberg exclusivement en PHP. Ce faisant, vous apprendrez à créer des sites WordPress plus légers, plus rapides et plus faciles à maintenir.
C’est plutôt passionnant, n’est-ce pas ? Commençons.
Que sont les blocs exclusivement en PHP et pourquoi sont-ils importants ?
La création d’un bloc Gutenberg nécessitait traditionnellement des compétences avancées en JavaScript côté serveur et en codage React. Cela constituait un obstacle à l’adoption de l’éditeur de blocs par les développeurs WordPress de longue date qui ne disposaient peut-être pas des connaissances nécessaires en React et Node.js.
Les choses changent désormais. À partir de Gutenberg 21.8, vous pouvez enregistrer des blocs Gutenberg en utilisant uniquement du PHP. Cela évite la complexité liée à la mise en place d’un environnement Node.js pour ceux qui ne travaillent pas avec du JavaScript côté serveur.
Grâce à l’enregistrement de blocs uniquement en PHP, vous pouvez enregistrer et afficher des blocs à la fois dans l’éditeur et en frontend en utilisant le même code PHP. Cela encourage les sites utilisant des thèmes hybrides ou des fonctions PHP traditionnelles et des codes courts à adopter et à développer sur l’éditeur de blocs.
Pour ceux qui souhaitent en savoir plus, voici les principales pull requests GitHub consacrées aux blocs uniquement en PHP.
- Autoriser l’enregistrement de blocs exclusivement en PHP : cette PR implémente l’enregistrement automatique des blocs côté serveur et renomme le support
auto_ssrenauto_register. - Blocs uniquement en PHP : transmettre toutes les métadonnées de l’enregistrement PHP au client : les blocs exclusivement en PHP prenant en charge
auto_registertransmettent désormais toutes les métadonnées de l’enregistrement PHP au client. - Blocs uniquement PHP : générer des contrôles d’inspection à partir des attributs : cette PR introduit la génération automatique de l’interface utilisateur (contrôles d’inspection) en fonction des attributs déclarés sur le serveur.
Comment créer votre premier bloc Gutenberg exclusivement en PHP
Lorsqu’un bloc est enregistré uniquement côté serveur — sans fichiers JS — et que le nouveau drapeau de prise en charge auto_register est défini sur true, l’éditeur utilise automatiquement le composant ServerSideRender pour enregistrer le bloc côté client et afficher l’aperçu du bloc. En substance, le contenu du bloc est désormais généré directement à partir du code PHP, tant dans l’éditeur que sur l’interface publique.
À titre d’illustration, voici un exemple PHP simple qui enregistre un bloc à l’aide de la méthode PHP-only.
/**
* Render callback (frontend and editor)
*/
function my_php_only_block_render( $attributes ) {
return '<div>
<h3>🚀 PHP-only Block</h3>
<p>This block was created with only PHP!</p>
</div>';
}
/**
* Register the block on the 'init' hook.
*/
add_action( 'init', function() {
register_block_type( 'my-plugin/php-only-test-block', array(
'title' => 'My PHP-only Block',
'icon' => 'welcome-learn-more',
'category' => 'text',
'render_callback' => 'my_php_only_block_render',
'supports' => array(
// Automatically registers the block in the Editor JS (previously auto_ssr)
'auto_register' => true,
),
) );
});
Vous pouvez tester ce code en le copiant-collant dans le fichier principal d’une extension personnalisée. Après avoir activé l’extension, vous devriez voir le bloc « Mon bloc uniquement en PHP » dans l’outil d’insertion de blocs.

La fonction register_block_type enregistre un type de bloc sur le serveur. Elle inclut désormais la nouvelle prise en charge auto_register, qui indique à Gutenberg de transmettre les métadonnées issues de l’enregistrement PHP.
La fonction accepte deux arguments :
- Le nom du type de bloc, y compris l’espace de noms. Dans cet exemple, le nom du bloc est
my-plugin/php-only-test-block. - Un tableau d’arguments pour le type de bloc. Dans le code ci-dessus, nous définissons
title,icon,category,render_callbacketsupports. Encore une fois, pour les types de blocs uniquement en PHP, le tableausupportsdoit inclure'auto_register' => true.
En plus de simplifier la création de types de blocs personnalisés et de faciliter leur intégration dans des thèmes hybrides, les blocs uniquement en PHP peuvent servir de conteneurs pour les fonctions PHP héritées et les codes courts. De plus, l’utilisation de blocs uniquement en PHP ouvre la voie à de nouvelles possibilités d’intégrations personnalisées et de fonctionnalités côté serveur.
Selon Héctor Priethor,
Un modèle d’enregistrement purement PHP simplifierait les exigences minimales pour le développement de blocs, les rendant accessibles à un public plus large de développeurs, et contribuerait à faire évoluer l’écosystème des blocs au-delà de l’utilisation avancée de JavaScript.
Utilisation d’attributs pour créer l’interface utilisateur des réglages de bloc
La PR 74102 permet la génération automatique de contrôles d’inspection à partir des définitions d’attributs des blocs. Cela permet aux utilisateurs de configurer l’apparence et les fonctionnalités de vos blocs exclusivement en PHP comme n’importe quel bloc Gutenberg enregistré via JavaScript.
Auparavant, vous deviez créer manuellement un fichier edit.js dans React et définir divers contrôles de réglages à l’aide de composants React.
Désormais, Gutenberg lit les définitions d’attributs et génère automatiquement les champs de saisie correspondants dans l’éditeur WordPress.
Le système mappe les types de données définis dans le tableau d’attributs aux définitions de champs DataForm.
'type' => 'string'génère un champ de texte.'type' => 'number'génère un champ numérique.'type' => 'integer'génère un champ entier.'type' => 'boolean'génère une case à cocher.'type' => 'string'avec'enum' => array()génère un champ de sélection.
Vous vous rendrez compte que vous ne pouvez utiliser que quelques contrôles. Si vous avez besoin de contrôles spécifiques, tels que RichText, RangeControl ou ToggleControl, vous devrez tout de même opter pour l’approche JS/React.
Cependant, cet ajout présente des avantages considérables. Les barrières à l’entrée sont encore abaissées, et vous n’aurez pas besoin d’apprendre React, Webpack ou NPM pour créer des blocs personnalisés avec de simples options modifiables.
Dans l’exemple suivant, nous étendons le bloc d’exemple présenté dans la section précédente en ajoutant quelques attributs.
/**
* 1. Define the block's HTML output.
*/
function my_php_only_block_render( $attributes ) {
// Extract attributes
$title = esc_html( $attributes['blockTitle'] );
$count = intval( $attributes['itemCount'] );
$enabled = $attributes['isEnabled']; // Boolean from the ToggleControl
$size = esc_attr( $attributes['displaySize'] );
// Start building the output
$output = sprintf( '<div class="my-php-block" style="font-size: %s; border: 1px solid #ccc; padding: 15px;">',
$size === 'large' ? '20px' : ($size === 'small' ? '12px' : '16px')
);
$output .= sprintf( '<h3>🚀 %s</h3>', $title );
// If the toggle is ON, show the list. If OFF, show a fallback message.
if ( $enabled ) {
$output .= '<ul>';
for ( $i = 1; $i <= $count; $i++ ) {
$output .= sprintf( '<li>Item %d</li>', $i );
}
$output .= '</ul>';
} else {
$output .= '<p><em>The list is currently disabled.</em></p>';
}
$output .= '</div>';
return $output;
}
/**
* 2. Register the block on 'init'.
*/
add_action( 'init', function() {
register_block_type( 'my-plugin/php-only-test-block', array(
'title' => 'My PHP-only Block',
'icon' => 'welcome-learn-more',
'category' => 'text',
'render_callback' => 'my_php_only_block_render',
// Attributes used to generate the Inspector UI
'attributes' => array(
'blockTitle' => array(
'type' => 'string',
'default' => 'PHP-only Block',
),
'itemCount' => array(
'type' => 'integer',
'default' => 3,
),
'isEnabled' => array(
'type' => 'boolean',
'default' => true,
),
'displaySize' => array(
'type' => 'string',
'enum' => array( 'small', 'medium', 'large' ),
'default' => 'medium',
),
),
'supports' => array(
'auto_register' => true,
),
) );
});
Un rapide coup d’œil à ce code montre à quel point il est facile d’enregistrer un bloc personnalisé avec tous ses réglages de configuration à l’aide de la nouvelle API. Les attributs sont désormais utilisés non seulement pour stocker les données saisies par l’utilisateur, mais aussi pour définir le schéma de l’interface utilisateur. Le code ci-dessus effectue les opérations suivantes :
- La fonction
register_block_typeenregistre le type de blocmy-plugin/php-only-test-block. - Le deuxième argument transmis à la fonction est un tableau contenant les éléments suivants :
title,icon,category,render_callback,attributesetsupports. - Le tableau
attributescontient les attributs du bloc. Dans l’exemple ci-dessus, le tableau comprend les élémentsblockTitle,itemCount,isEnabledetdisplaySize. 'auto_register' => trueactive l’enregistrement automatique côté serveur.
Voici ce que fait la fonction de rappel my_php_only_block_render :
- Tout d’abord, la fonction extrait les valeurs des attributs du tableau
$attributeset les attribue aux variables$title,$count,$enabledet$size. - Ensuite, elle génère le contenu du bloc.
Voici le résultat à l’écran :

Un exemple concret de blocs uniquement en PHP
Bien qu’il existe de nombreux cas de figure où JavaScript reste nécessaire, vous pouvez déjà faire beaucoup avec des blocs exclusivement en PHP, en particulier lorsqu’ils sont utilisés avec des propriétés de bloc.
Dans l’exemple suivant, nous utilisons la fonction get_block_wrapper_attributes(), qui génère une chaîne d’attributs pour le bloc en cours de rendu. Le bloc recevra automatiquement les couleurs, les bordures et les ombres définies par l’utilisateur, et appliquera les styles correspondants au conteneur principal. De cette manière, le bloc est personnalisable via les outils natifs de Gutenberg, tout comme un bloc basé sur React.
Pour voir cela en action, créez un dossier smart-pricing-widget sur votre ordinateur. Dans ce dossier, créez un fichier style.css contenant le code CSS suivant :
/* style.css */
.pricing-card {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
box-sizing: border-box;
}
.pricing-card h3 {
margin: 0;
font-size: 1.5rem;
}
.pricing-card .price-value {
font-size: 3.5rem;
font-weight: 800;
margin: 15px 0;
}
.pricing-card ul {
list-style: none;
padding: 25px 0;
margin: 20px 0;
width: 100%;
border-top: 1px solid rgba(128,128,128,0.3);
display: flex;
flex-direction: column;
gap: 12px;
}
.pricing-card li {
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
}
.pricing-card .cta-button {
margin-top: auto;
padding: 15px 25px;
border-radius: 8px;
text-decoration: none;
font-weight: bold;
transition: opacity 0.2s;
}
.pricing-card .cta-button:hover {
opacity: 0.8;
}
/* Variantes de thème */
.pricing-card.theme-light { background-color: #ffffff; color: #000000; }
.pricing-card.theme-light .cta-button { background-color: #21759b; color: #ffffff; }
.pricing-card.theme-dark { couleur de fond : #1a1a1a ; couleur : #ffffff ; }
.pricing-card.theme-dark .cta-button { couleur de fond : #ffffff ; couleur : #1a1a1a ; }
.pricing-card.theme-blue { background-color: #21759b; color: #ffffff; }
.pricing-card.theme-blue .cta-button { background-color: #000000; color: #ffffff; }
/* Classes utilitaires */
.pricing-card .is-full-width {
width: 100%;
display: block;
align-self: stretch;
}
Nous ne commenterons pas ce code, car il s’agit d’une simple feuille de style pour votre bloc de widget.
Créez maintenant le fichier principal de votre extension, nommez-le smart-pricing-widget.php, puis collez-y le code suivant :
<?php
/**
* Plugin Name: Smart Pricing Widget
* Plugin URI: https://example.com/
* Description: PHP-only Pricing Table block
* Version: 1.2.0
* Author: Your Name
* Text Domain: smart-pricing-widget
*/
if ( ! defined( 'ABSPATH' ) ) exit;
/**
* Render callback
*/
function render_smart_pricing_block( $attributes ) {
$plan_name = esc_html( $attributes['planName'] );
$price = intval( $attributes['price'] );
$theme = $attributes['blockTheme'];
$btn_text = esc_html( $attributes['buttonText'] );
$btn_size = $attributes['buttonSize'];
$features_raw = $attributes['featuresList'];
$features_array = array_filter( array_map( 'trim', explode( ',', $features_raw ) ) );
$wrapper_attributes = wp_kses_data( get_block_wrapper_attributes( array(
'class' => "pricing-card theme-{$theme}",
) ) );
$output = sprintf( '<div %s>', $wrapper_attributes );
$output .= sprintf( '<h3>%s</h3>', $plan_name );
$output .= sprintf( '<div class="price-value">€%d</div>', $price );
if ( ! empty( $features_array ) ) {
$output .= '<ul>';
foreach ( $features_array as $feature ) {
$is_checked = strpos( $feature, '+' ) === 0;
$clean_text = esc_html( ltrim( $feature, '+- ' ) );
$icon = $is_checked ? '✅' : '❌';
$style = $is_checked ? '' : 'style="opacity: 0.6;"';
$output .= sprintf( '<li %s><span>%s</span> %s</li>', $style, $icon, $clean_text );
}
$output .= '</ul>';
}
$btn_class = 'cta-button' . ( $btn_size === 'full' ? ' is-full-width' : '' );
$output .= sprintf( '<a href="#" class="%s">%s</a>', esc_attr( $btn_class ), $btn_text );
$output .= '</div>';
return $output;
}
/**
* Register Assets and Block
*/
add_action( 'init', function() {
// 1. Register the CSS file
wp_register_style(
'smart-pricing-style',
plugins_url( 'style.css', __FILE__ ),
array(),
'1.2.0'
);
// 2. Register the Block
register_block_type( 'tutorial/smart-pricing', array(
'api_version' => 3,
'title' => 'Pricing Card',
'icon' => 'cart',
'category' => 'widgets',
'render_callback' => 'render_smart_pricing_block',
// Link the registered style handle here
'style' => 'smart-pricing-style',
'attributes' => array(
'planName' => array( 'type' => 'string', 'default' => 'Professional' ),
'price' => array( 'type' => 'integer', 'default' => 49 ),
'buttonText' => array( 'type' => 'string', 'default' => 'Choose Plan' ),
'buttonSize' => array( 'type' => 'string', 'enum' => array( 'auto', 'full' ), 'default' => 'auto' ),
'blockTheme' => array( 'type' => 'string', 'enum' => array( 'light', 'dark', 'blue' ), 'default' => 'light' ),
'featuresList' => array( 'type' => 'string', 'default' => "+ Support, + Updates, - Domain" ),
),
'supports' => array(
'auto_register' => true,
'color' => array( 'background' => true, 'text' => true ),
'spacing' => array( 'margin' => true, 'padding' => true ),
'typography' => array( 'fontSize' => true ),
'shadow' => true,
'__experimentalBorder' => array( 'color' => true, 'radius' => true, 'style' => true, 'width' => true ),
'border' => array( 'color' => true, 'radius' => true, 'style' => true, 'width' => true ),
),
) );
});
Ce script comprend deux fonctions. La fonction register_block_type() est le moteur de votre plugin. Voici ses principaux éléments :
- Le premier argument est l’identifiant du bloc, incluant l’espace de noms (
tutorial/smart-pricing). - Le deuxième argument est un tableau d’arguments. Dans le code ci-dessus, nous avons défini la version de l’API, le titre, l’icône, la catégorie, la fonction de rappel de rendu, le style, les attributs et les supports.
- Les attributs du tableau génèrent les contrôles que les utilisateurs utiliseront pour ajouter du contenu et configurer le bloc. L’élément
typespécifie le type de contrôle à ajouter à l’inspecteur de bloc. Dans cet exemple, il s’agit de champs de texte ('type’ => 'string’), d’un entier ('type’ => 'integer’) et de deux menus déroulants ('type’ => 'string’, 'enum’ => array()). - Les éléments du tableau
supportsajoutent des fonctionnalités qui permettent de personnaliser le style du bloc. Comme nous l’avons mentionné précédemment, le seul support requis dans un bloc uniquement PHP estauto_register, qui permet la génération automatique de l’interface utilisateur pour les attributs personnalisés. Les autres supports déclarés ci-dessus incluent color, spacing, typography, shadow et border.
La fonction de rappel render_smart_pricing_block() génère le code HTML du bloc. Voici une description détaillée du fonctionnement de cette fonction :
- Elle extrait et nettoie les attributs du bloc, puis ajoute le code CSS qui génère l’apparence du bloc dans l’interface publique et l’éditeur.
- Les fonctionnalités à afficher dans le bloc (
$attributes['featuresList'];) sont gérées séparément. Actuellement, il n’est pas possible d’ajouter des contrôles avancés à la colonne latérale des réglages du bloc. Pour créer une liste, telle qu’une liste de fonctionnalités, vous ne pouvez utiliser qu’un simple champ de texte. Dans cet exemple, vous devez saisir manuellement les fonctionnalités du produit, séparées par des virgules. - La variable
$wrapper_attributesest un conteneur pour les attributs du wrapper fournis par la fonctionget_block_wrapper_attributes. Cette fonction ne se contente pas d’ajouter les classes spécifiées dans le code (pricing-card theme-{$theme}), mais récupère automatiquement toutes les personnalisations de style que l’utilisateur définit dans l’inspecteur de bloc, y compris les couleurs, les bordures, le remplissage, la marge, l’ombre, la typographie et les classes de bloc standard (wp-block-tutorial-smart-pricing). wp_kses_datagarantit qu’il n’y a pas de balises ou de scripts malveillants (XSS) dans la chaîne.- Le reste du code génère le contenu du bloc.
Activez l’extension et créez un nouvel article ou une nouvelle page. Ouvrez l’éditeur de blocs et faites défiler vers le bas jusqu’à la section Widgets. Vous devriez y voir votre bloc « Pricing Card », identifié par une icône de panier.

L’image ci-dessus montre le bloc avec le thème clair par défaut.
Sur l’image ci-dessous, vous pouvez voir la version sombre du bloc ainsi que les réglages que vous avez définis dans votre extension.

L’image suivante montre les commandes de style que vous avez ajoutées grâce aux fonctionnalités de prise en charge des blocs.

Il convient également de noter que les styles ajoutés par les extensions remplacent les styles du thème du bloc. Cela permet une plus grande personnalisation de l’apparence du bloc, comme le montre l’image suivante :

Convertir les codes courts hérités en blocs Gutenberg avec du PHP pur
L’une des utilisations les plus directes des blocs PHP est celle de conteneurs de codes courts. Avec Gutenberg, vous pouvez toujours utiliser des codes courts dans votre contenu, mais vous devez insérer manuellement votre code court dans un bloc Code court, ce qui n’est pas l’expérience la plus agréable.
Supposons que vous disposiez du code court suivant :
function my_custom_alert_shortcode( $atts ) {
$options = shortcode_atts( array(
'type' => 'info',
'message' => 'Default alert message',
), $atts );
$styles = array(
'info' => 'background: #d1ecf1; color: #0c5460; border-color: #bee5eb;',
'warning' => 'background: #fff3cd; color: #856404; border-color: #ffeeba;',
'error' => 'background: #f8d7da; color: #721c24; border-color: #f5c6cb;'
);
$style = $styles[ $options['type'] ] ?? $styles['info'];
return sprintf(
'<div class="sc-alert-box" style="%s padding: 20px; border: 1px solid; border-radius: 6px; margin: 10px 0;">
<strong style="text-transform: uppercase;">%s:</strong> %s
</div>',
esc_attr( $style ),
esc_html( $options['type'] ),
esc_html( $options['message'] )
);
}
add_shortcode( 'sc_alert', 'my_custom_alert_shortcode' );
Ce code génère une simple boîte que vous pouvez insérer dans votre contenu à l’aide du code court suivant :
[sc_alert type="alert" message="Bonjour"]
Dans Gutenberg, vous utiliserez un bloc Code court pour insérer la boîte dans votre contenu, comme le montre l’image suivante :

Le scénario change complètement avec les blocs PHP-only. Vous pouvez désormais encapsuler votre shortcode dans un bloc Gutenberg PHP-only et le configurer via les commandes de l’interface utilisateur. Voici le code à ajouter à votre extension :
/**
* Rendering callback
*/
function render_shortcode_alert_wrapper_block( $attributes ) {
$type = esc_attr( $attributes['alertType'] );
$message = esc_attr( $attributes['alertMessage'] );
$shortcode_string = sprintf( '[sc_alert type="%s" message="%s"]', $type, $message );
$wrapper_attributes = wp_kses_data( get_block_wrapper_attributes( array(
'class' => 'wp-block-shortcode-alert-wrapper',
) ) );
return sprintf(
'<div %s>%s</div>',
$wrapper_attributes,
do_shortcode( $shortcode_string )
);
}
/**
* Register the block type on the server
*/
add_action( 'init', function() {
register_block_type( 'tutorial/alert-wrapper', array(
'api_version' => 3,
'title' => 'Alert (Shortcode wrapper)',
'icon' => 'feedback',
'category' => 'widgets',
'render_callback' => 'render_shortcode_alert_wrapper_block',
'attributes' => array(
'alertType' => array(
'type' => 'string',
'enum' => array( 'info', 'warning', 'error' ),
'default' => 'info',
),
'alertMessage' => array(
'type' => 'string',
'default' => 'Type your alert message here...',
),
),
'supports' => array(
'auto_register' => true,
'spacing' => array( 'margin' => true, 'padding' => true ),
'typography' => array( 'fontSize' => true ),
),
) );
});
Le code ci-dessus est similaire à celui de la section précédente. Ce qui change ici, c’est la fonction de rappel de rendu.
$shortcode_stringstocke la chaîne de code court ([sc_alert type="%s" message="%s"]).- La fonction renvoie le code HTML du conteneur de bloc et le code court inclus (
do_shortcode( $shortcode_string )).
À présent, ouvrez l’outil d’insertion de blocs et recherchez le bloc « Shortcode wrapper » parmi les widgets. Insérez-le dans votre contenu et configurez-le à partir de la colonne de réglages du bloc. Le bloc apparaîtra de manière identique dans l’éditeur et sur l’interface publique.

Comment le développement WordPress évolue-t-il avec les blocs uniquement en PHP ?
À l’heure actuelle, les blocs PHP purs sont en phase expérimentale et leurs capacités restent limitées. Gutenberg offre des fonctionnalités plus puissantes, telles que les modèles de blocs et les variantes de blocs, qui fournissent toutes les fonctionnalités d’édition des blocs Gutenberg natifs et des blocs personnalisés créés en JavaScript. Il existe toutefois des cas de figure où les blocs PHP offrent des opportunités significatives.
Tout d’abord, les blocs uniquement en PHP devraient favoriser une adoption plus large de l’éditeur de blocs, en particulier parmi les développeurs WordPress moins orientés vers le développement JavaScript côté serveur.
De plus, ils constituent des conteneurs idéaux pour les fonctions personnalisées et les shortcodes, comme le montre l’exemple présenté dans cet article. Ils permettent également une intégration aisée avec des services externes.
Et nous pouvons raisonnablement nous attendre à de futures améliorations et ajouts de fonctionnalités, à davantage de contrôles de configuration, ainsi qu’à des intégrations avec les outils Gutenberg existants.
Une chose est sûre : grâce aux blocs uniquement en PHP, la création de blocs Gutenberg est devenue beaucoup plus simple.
Si le développement WordPress est votre métier, Kinsta vous fournit les outils de développement dont vous avez besoin, vous permettant de vous concentrer sur le développement WordPress, sans avoir à vous soucier de configurations complexes ni de tâches de maintenance fastidieuses : SSH, SFTP, intégration Git, mises à jour automatiques, environnement de staging en un clic, outil de développement local intégré, et bien plus encore. Essayez-le par vous-même grâce à votre premier mois gratuit.