Cet article montre aux développeurs comment créer un shortcode, une balise entre crochets comme [sh_notice] que les rédacteurs tapent dans un article et que WordPress remplace par du vrai HTML à l’affichage. Les premières versions échouent souvent de l’une de trois façons : le contenu atterrit en haut de l’article, l’encadré ramasse des balises de paragraphe parasites, ou un attribut arrive dans la page sans être échappé. La solution consiste à enregistrer la balise sur init, à fusionner les attributs avec des valeurs par défaut grâce à shortcode_atts(), à échapper chaque valeur et à renvoyer une chaîne au lieu de l’afficher. L’échappement, qui transforme les caractères comme < en texte inoffensif, compte parce que quiconque peut écrire un brouillon, y compris le rôle Contributeur, peut taper un shortcode.
Ce que vous allez accomplir
- Un shortcode
[sh_notice]dans une petite extension, avec les attributstypeettitleet du contenu encadré. - Des valeurs par défaut pour chaque attribut, une liste autorisée pour les valeurs qui finissent dans des classes CSS, et l’échappement de tout le reste.
- Une feuille de style qui se charge seulement sur les pages qui contiennent le shortcode.
- Un hook qui permet à un thème de changer les valeurs par défaut sans modifier l’extension.
- Des vérifications WP-CLI qui montrent exactement le HTML produit par le shortcode, y compris quand on lui donne une mauvaise entrée.
Prérequis
- WordPress 6.0 ou plus récent (7.x compris) et PHP 8.1 ou plus récent. L’API des shortcodes est stable depuis des années, alors toutes les versions depuis se comportent de la même façon.
- Un accès aux fichiers de
wp-content/plugins/, et un compte administrateur pour activer l’extension. - WP-CLI, qui pilote WordPress depuis le terminal, pour les tests. Chaque vérification a aussi son équivalent dans le fureteur.
- Un article de test que vous pouvez modifier. Les exemples en utilisent un à
https://example.com/maintenance-window/.
Comment ça fonctionne
add_shortcode( 'sh_notice', 'sh_notice_shortcode' ) ajoute le nom de la balise et sa fonction de rappel à une liste globale. Rien d’autre ne se passe avant l’affichage d’une page. Quand WordPress imprime un article, il fait passer le contenu par le filtre the_content. À la priorité 11 de ce filtre, do_shortcode() cherche dans le texte chaque balise enregistrée et appelle la fonction correspondante une fois par occurrence. La fonction reçoit trois arguments : les attributs sous forme de tableau, le contenu encadré (ou null s’il n’y a pas de balise fermante) et le nom de la balise. La chaîne qu’elle renvoie remplace la balise dans le texte.
Deux détails de ce parcours expliquent la plupart des bogues de shortcodes. La mise en forme des paragraphes passe avant, à la priorité 10, alors le contenu encadré arrive déjà découpé en balises <p>. Dans l’éditeur de blocs, le bloc Code court applique la même mise en forme à l’affichage. Et WordPress utilise seulement la valeur que votre fonction renvoie. Tout ce que la fonction affiche avec echo part directement au fureteur avant le contenu de l’article, d’où son apparition en haut.
Nommez les balises avec des lettres minuscules et des traits de soulignement, et commencez-les par un préfixe comme sh_. Les noms de balises partagent une seule liste globale, alors un nom générique comme [notice] peut être repris par la prochaine extension qui l’enregistre. L’article sur les hooks explique pourquoi init est le moment sûr pour l’enregistrement.
Étapes
- Créez l’extension. Créez un dossier et une feuille de style vide :
mkdir -p wp-content/plugins/sh-notice
touch wp-content/plugins/sh-notice/sh-notice.php wp-content/plugins/sh-notice/notice.css
Aucune sortie : les deux fichiers existent. Si la structure d’une extension est nouvelle pour vous, l’article sur le squelette d’extension explique comment elle grandit au-delà d’un seul fichier.
- Enregistrez le shortcode et écrivez la fonction. Mettez ceci dans
sh-notice.php:
<?php
/**
* Plugin Name: SH Notice
* Description: Adds the [sh_notice] shortcode.
*/
add_action( 'init', 'sh_register_notice_shortcode' );
function sh_register_notice_shortcode() {
add_shortcode( 'sh_notice', 'sh_notice_shortcode' );
}
function sh_notice_shortcode( $atts, $content = null, $tag = '' ) {
$atts = shortcode_atts(
array(
'type' => 'info',
'title' => '',
),
$atts,
$tag
);
$types = array( 'info', 'success', 'warning' );
$type = in_array( $atts['type'], $types, true ) ? $atts['type'] : 'info';
wp_enqueue_style( 'sh-notice' );
$html = '<div class="sh-notice sh-notice--' . esc_attr( $type ) . '" role="note">';
if ( '' !== $atts['title'] ) {
$html .= '<p class="sh-notice__title">' . esc_html( $atts['title'] ) . '</p>';
}
$html .= '<div class="sh-notice__body">' . do_shortcode( (string) $content ) . '</div>';
$html .= '</div>';
return $html;
}
Chaque partie a un rôle. shortcode_atts() garde seulement les attributs que vous listez, remplit une valeur par défaut pour ceux que le rédacteur a omis et laisse tomber le reste. Passer $tag comme troisième argument rend aussi les valeurs par défaut filtrables, ce que l’étape 5 utilise. La liste autorisée $types fait qu’une faute comme type="warnign" retombe sur info au lieu de produire une classe CSS invalide. esc_attr() et esc_html() transforment les caractères comme < et " en texte inoffensif. Le do_shortcode() intérieur permet aux rédacteurs de placer d’autres shortcodes dans l’avis. La ligne wp_enqueue_style() est expliquée à l’étape 4.
Vérifiez la syntaxe, puis activez :
php -l wp-content/plugins/sh-notice/sh-notice.php
wp plugin activate sh-notice
No syntax errors detected in wp-content/plugins/sh-notice/sh-notice.php
Plugin 'sh-notice' activated.
Success: Activated 1 of 1 plugins.
- Affichez-le en ligne de commande.
do_shortcode()exécute le même analyseur que WordPress utilise pour les articles, alors vous pouvez tester sans ouvrir l’éditeur :
wp eval 'echo do_shortcode( "[sh_notice type=\"warning\" title=\"Heads up\"]Backups run at 02:00.[/sh_notice]" ) . PHP_EOL;'
<div class="sh-notice sh-notice--warning" role="note"><p class="sh-notice__title">Heads up</p><div class="sh-notice__body">Backups run at 02:00.</div></div>
Si la sortie est la balise entre crochets elle-même, inchangée, le shortcode n’est pas enregistré. Vérifiez que l’extension est active avec wp plugin list --name=sh-notice.
- Chargez la feuille de style seulement là où le shortcode apparaît. Ajoutez ceci à
sh-notice.php:
add_action( 'wp_enqueue_scripts', 'sh_notice_assets' );
function sh_notice_assets() {
wp_register_style(
'sh-notice',
plugins_url( 'notice.css', __FILE__ ),
array(),
(string) filemtime( plugin_dir_path( __FILE__ ) . 'notice.css' )
);
$post = get_post();
if ( is_singular() && $post && has_shortcode( $post->post_content, 'sh_notice' ) ) {
wp_enqueue_style( 'sh-notice' );
}
}
Sur un article ou une page qui contient la balise, has_shortcode() renvoie true et la feuille de style va dans le <head>. L’appel à wp_enqueue_style() dans la fonction de l’étape 2 sert de filet de sécurité. Il couvre les endroits que has_shortcode() ne voit pas, comme un widget, et WordPress ajoute alors la feuille de style plus loin dans la page. Depuis la 6.9, il la remonte généralement dans le <head> pour vous. L’article sur l’inclusion des scripts et des styles explique plus en détail les identifiants, les versions et les hooks.
- Laissez un thème changer les valeurs par défaut. Comme l’étape 2 passe
$tagàshortcode_atts(), WordPress exécute un filtre nomméshortcode_atts_sh_noticechaque fois qu’il fusionne les attributs. Un thème ou une autre extension peut s’en servir pour fixer une valeur par défaut pour tout le site sans toucher à votre code :
add_filter( 'shortcode_atts_sh_notice', 'sh_child_notice_defaults', 10, 3 );
function sh_child_notice_defaults( $out, $pairs, $atts ) {
if ( ! isset( $atts['type'] ) ) {
$out['type'] = 'success';
}
return $out;
}
La vérification isset() compte. Sans elle, le filtre écraserait un type que le rédacteur a tapé exprès.
Vérifiez la nouvelle valeur par défaut avec un avis qui ne précise aucun type :
wp eval 'echo do_shortcode( "[sh_notice]Hi[/sh_notice]" ) . PHP_EOL;'
<div class="sh-notice sh-notice--success" role="note"><div class="sh-notice__body">Hi</div></div>
- Utilisez-le dans l’éditeur. Dans l’éditeur de blocs, ajoutez un bloc Code court et tapez la balise et son contenu sur une seule ligne :
[sh_notice type="warning" title="Maintenance window"]The store is read-only from 02:00 to 02:30 on Sunday.[/sh_notice]
L’éditeur montre la balise brute, parce que les shortcodes s’exécutent seulement à l’affichage de la page. Prévisualisez l’article pour voir l’encadré.
Vérifier que ça fonctionne
Le shortcode est enregistré.
wp eval 'var_dump( shortcode_exists( "sh_notice" ) );'
bool(true)
Une mauvaise entrée ressort inoffensive. Donnez-lui du balisage dans le titre et un type inconnu :
wp eval 'echo do_shortcode( "[sh_notice type=\"bogus\" title=\"<b>Bold</b>\"]Hi[/sh_notice]" ) . PHP_EOL;'
<div class="sh-notice sh-notice--info" role="note"><p class="sh-notice__title"><b>Bold</b></p><div class="sh-notice__body">Hi</div></div>
Le type est retombé sur info, et les balises <b> sont devenues du texte visible au lieu de balisage.
La page en ligne montre du HTML, pas des crochets. Publiez l’article de test, puis récupérez-le :
curl -s https://example.com/maintenance-window/ | grep -oE 'class="sh-notice sh-notice--[a-z]+"|id=.sh-notice-css.'
curl -s https://example.com/maintenance-window/ | grep -c '\[sh_notice'
Exemple de sortie :
id='sh-notice-css'
class="sh-notice sh-notice--warning"
0
La balise de la feuille de style, la classe de l’avis et un compte de 0 balise brute veulent dire que tout a fonctionné. Lancez la première commande sur un article sans le shortcode : elle ne doit rien afficher.
Dépannage
La page affiche [sh_notice] en texte brut. La balise n’a jamais été traitée. Soit l’extension est inactive, soit le nom de la balise dans l’article ne correspond pas exactement à add_shortcode(), soit le texte est imprimé par du code qui contourne the_content. Un thème qui affiche un champ personnalisé avec echo get_post_meta( ... ) en est un cas fréquent. Enveloppez cette sortie dans do_shortcode(), ou déplacez le contenu dans le corps de l’article.
L’avis apparaît en haut de l’article. La fonction affiche avec echo au lieu de renvoyer une chaîne. Si votre HTML vit dans un fichier gabarit, capturez-le avec la mise en mémoire tampon de sortie et renvoyez le résultat :
ob_start();
include plugin_dir_path( __FILE__ ) . 'templates/notice.php';
return ob_get_clean();
Des paragraphes vides ou des <br /> parasites dans l’encadré. La mise en forme des paragraphes est passée avant votre shortcode, alors les sauts de ligne autour du contenu encadré sont devenus des balises <p> et <br />. Gardez la balise ouvrante, le contenu et la balise fermante sur une seule ligne, comme à l’étape 6. Un saut de ligne juste après la balise ouvrante ou avant la balise fermante devient un <br /> dans l’encadré, et une ligne vide laisse un </p> ou un <p> orphelin.
Un attribut est ignoré. Seuls les attributs listés dans les valeurs par défaut de shortcode_atts() survivent, alors vérifiez d’abord l’orthographe à cet endroit. WordPress met aussi les noms d’attributs en minuscules : Title="..." arrive sous la forme title. Le texte collé depuis un traitement de texte apporte souvent des guillemets typographiques, comme dans type=”warning”. L’analyseur ne les reconnaît pas comme des guillemets, la valeur est donc fausse et la liste autorisée retombe sur info. Retapez les guillemets en guillemets droits.
Deux avis se fondent en un seul. Utiliser le même shortcode avec et sans balise fermante dans un même article mélange l’analyseur. Un [sh_notice] non fermé suivi plus loin de [sh_notice]...[/sh_notice] est lu comme un seul long avis. Fermez toujours ce shortcode, ou enregistrez une balise distincte pour la forme sans fermeture.
Quand ce n’est pas la bonne approche
Sur un site bâti avec l’éditeur de blocs, un bloc personnalisé sert généralement mieux les rédacteurs. Ils voient le vrai encadré pendant qu’ils écrivent, choisissent le type dans un menu au lieu de le taper, et rien ne casse à cause des guillemets typographiques. Le flux de développement de blocs explique comment en construire un. Si le contenu ne change jamais, une composition synchronisée ne demande aucun code.
Les shortcodes lient aussi votre contenu à l’extension. Si elle est un jour désactivée, chaque article qui utilise la balise affiche des crochets bruts. Avant d’en retirer un, trouvez où il sert :
wp post list --post_type=any --s='[sh_notice' --fields=ID,post_title,post_status
Chaque ligne est un article à modifier avant de désactiver l’extension. Un résultat vide veut dire qu’aucun article n’utilise la balise.
Enfin, un shortcode s’exécute à chaque affichage de page. Si le vôtre interroge la base de données ou appelle une API externe, mettez le résultat en cache dans un transient (une valeur stockée avec une date d’expiration) au lieu de refaire le travail chaque fois. La documentation officielle de l’API des shortcodes couvre les autres cas limites.
Un WordPress qui rapporte vraiment mérite un opérateur — Stack Harbor opère cette pile sous WordPress Entreprise ; réservez une consultation d’infrastructure.