Pour des raisons de sécurité, on ne peut pas insérer un bout de code PHP dans le contenu d’un article ou d’une page. Un code court (ou shortcode) est un moyen d’insérer du contenu dynamique dans le contenu statique de vos pages ou autres publications.

Un code court WordPress se présente sous la forme [mon_super_code_court]. Un code court étant simplement une macro appelant une fonction PHP, vous pouvez faire un peu ce que vous voulez à l’intérieur. Par exemple, beaucoup d’extensions nécessitent la création de pages spéciales pour leurs fonctionnalités et souvent, il suffit de créer une nouvelle page avec un simple code court pour que la magie opère !

Prenez WooCommerce, par exemple. Les pages du panier et de validation de la commande sont entièrement gérées par de simples shortcodes. On peut difficilement faire plus simple.

Créer un code court

Créer un code court est ultra simple. Il suffit d’utiliser la fonction add_shortcode().

La fonction add_shortcode() est disponible très tôt lors du chargement de WordPress, tout comme add_action() ou add_filter(). Ce qui signifie que l’on peut parfaitement l’utiliser nue (c’est-à-dire hors d’une fonction de rappel hookée), comme on utilise add_action() ou add_filter() nus pour hooker nos fonctions.

Cela dit, de manière générale, que ce soit dans un thème ou une extension, on n’exécute pas de code directement mais on programme l’exécution de nos fonctions sur les hooks de WordPress. Les fonctions que l’on peut utiliser directement dans un thème ou une extension sont rares et add_action(), add_filter() et add_shortcode() en font partie.

Dites-vous juste que par défaut, on hooke tout. Toujours. Pas de code nu. Dans une petite extension, ajoutez le code suivant :

// In main plugin file
add_shortcode( 'example_simple_shortcode', 'example_simple_shortcode' );
/**
 * Our simple shortcode example callback function
 *
 * @param   array   $atts     Array of shortcode attributes
 * @param   string  $content  Content between shortcode tags.
 * @param   string  $tag      Shortcode tag itself
 * @return  string            String of html content
 */
function example_simple_shortcode( $atts = array(), $content ='', $tag = 'example_simple_shortcode' ){
    ob_start();
    ?>
        <strong><?php _e( 'Shortcode attributes :', 'example' ); ?></strong>
        <pre><?php var_dump( $atts ); ?></pre>
        <strong><?php _e( 'Shortcode content :', 'example' ); ?></strong>
        <pre><?php var_dump( $content ); ?></pre>
        <strong><?php _e( 'Shortcode tag :', 'example' ); ?></strong>
        <pre><?php var_dump( $tag ); ?></pre>
    <?php
    return ob_get_clean();
}

add_shortcode( string $tag, callable $callback )

La fonction add_shortcode() est très simple. On lui passe le nom de notre code court $tag et le nom de la fonction de rappel qui lui est associée. Donc dans notre exemple, on déclare un code court appelé example_simple_shortcode, qui a pour fonction de rappel une fonction du même nom.

Quand WordPress tombera sur le nom de notre code court entre crochets ([example_simple_shortcode]) dans le contenu d’une page ou autre publication, il exécutera notre fonction de rappel, et y collera ce que la fonction lui renvoie. C’est pourquoi il faut absolument que la fonction de rappel renvoie une chaine ! Les codes courts fonctionnent un peu comme les filtres. Le code entré entre crochets est en quelque sorte remplacé par la valeur de retour de la fonction de rappel.

La fonction de rappel prend trois paramètres :

  • $atts est un tableau des attributs passés au code court. Ce sont ses paramètres, en quelque sorte. Plus de détails sur ce point dans la section suivante.
  • $content est le contenu du code court, si le code court est de type balise. Pas de panique, on y vient.
  • $tag est le nom du code court lui-même. Facile.

Notre fonction de rappel example_simple_shortcode() va pour le moment juste afficher les valeurs de ses trois paramètres. Pardon. Elle ne va rien afficher du tout. Elle va retourner une chaine de caractères contenant l’HTML nécessaire pour afficher les valeurs de ses trois paramètres, grâce à ob_start() et ob_get_clean().

Ces fonctions sont très pratiques. ob_start() va permettre de ne rien afficher, mais de mettre tout ce qui devrait être affiché ensuite en mémoire tampon. Puis on retourne le contenu du tampon et on le vide avec ob_get_clean(). Personnellement, je les utilise beaucoup quand je dois afficher de l’HTML dans une fonction PHP.

Le code court affiche ses paramètres.
Le code court affiche simplement les paramètres de sa fonction de rappel.

Les attributs des codes courts

Pour personnaliser le contenu de notre code court, on peut passer des attributs dans le code court. On les passe simplement entre les crochets, sous la forme clé="valeur". Par exemple, si on retourne dans l’édition de notre page, et qu’on insère un attribut title à notre code court, comme ceci :

[example_simple_shortcode title="Exemple de code court"]

On peut voir que sur le devant du site, notre attribut apparaît dans le tableau affiché. On peut récupérer ce titre dans la fonction de rappel du code court, pour l’afficher ensuite.

function example_simple_shortcode( $atts = array(), $content ='', $tag = 'example_simple_shortcode' ){
    ob_start();
    ?>
        <?php if( ! empty( $atts['title'] ) ): ?>
            <h2><?php echo esc_html( $atts['title'] ); ?></h2>
        <?php endif; ?>
        ...
    <?php
    return ob_get_clean();
}

Sur le devant du site, on a bien notre titre qui s’affiche.

Le code court affiche bien notre titre.
Le code court affiche bien notre titre.

On peut passer autant d’attributs que nécessaire. Si vous voulez ajouter dix attributs, pas de souci. Ils se retrouveront tous dans le même tableau $atts.

Attributs par défaut

Dans l’exemple, j’ai été prudent et j’ai vérifié qu’il y avait bien un titre donné en attribut. Mais s’il n’y en a pas, on a peut-être besoin d’inclure un titre par défaut.

Pour ce faire, on va utiliser la fonction shortcode_atts( array $pairs, array $atts, string $shortcode = '' ).

Elle prend un tableau $pairs de tous les attributs supportés par le shortcode et de leur valeur par défaut, les attributs passés dans le code court $atts, et le nom de notre code court, qui peut être passé comme contexte. En effet, le retour de la fonction est filtrable (via le hook shortcode_atts_{$shortcode}) donc cela peut être de passer le nom du code court pour exposer le hook.

La fonction va retourner un tableau en fusionnant nos attributs par défaut avec les attributs passés au code court. C’est très pratique.

function example_simple_shortcode( $atts, $content = '', $tag = 'example_simple_shortcode' ){

    $defaults = array(
        'title' => __( 'Default title', 'example' ),
    );
    $atts = shortcode_atts( $defaults, $atts, $tag );

    ob_start();
    ?>
        <h2><?php echo esc_html( $atts['title'] ); ?></h2>
        ...
    <?php
    return ob_get_clean();
}

On déclare des attributs et leur valeur par défaut, et on fusionne ce tableau avec $atts. Plus besoin de vérifier qu’on a bien un attribut title car on en aura un dans tous les cas. Easy.

Si on supprime notre attribut title dans le contenu de notre page, alors on a bien quand même un titre.

Le code court affiche bien notre titre par défaut.
Le titre par défaut s’affiche si on ne passe pas d’attributs.

Codes courts doubles

On peut aussi créer des codes courts qui fonctionnent comme des balises HTML et qui vont donc encadrer du contenu. Dans notre éditeur de contenu, il suffit d’encadrer le contenu que l’on souhaite avec des codes courts [mon_code_court] et [/mon_code_court].

Par exemple, imaginons que nous voulions mettre en avant un paragraphe ou bloc de contenu, en le contenant dans une <div> avec des styles particuliers. Créons un nouveau code court.

// In main plugin file
add_shortcode( 'example_enclosing_shortcode', 'example_enclosing_shortcode' );
/**
 * A simple enclosing shortcode example.
 *
 * @param   array   $atts     Array of shortcode attributes
 * @param   string  $content  Content between shortcode tags.
 * @param   string  $tag      Shortcode tag itself
 * @return  string            String of html content
 */
function example_enclosing_shortcode( $atts = array(), $content = '', $tag = 'example_enclosing_shortcode' ){

    if( empty( $content ) ){
        return __( 'You forgot to include content to emphasize !', 'example' );
    }

    ob_start();
    ?>
        <div style="background-color: yellow; padding: 1.5rem; font-size: 1.125em;"><?php echo $content; ?></div>
    <?php
    return ob_get_clean();
}

Le contenu entre nos codes courts balises est passé à la fonction de rappel via le paramètre $content. On vérifie donc que notre contenu n’est pas vide. S’il l’est, on retourne un message d’erreur à afficher. Concrètement, il vaudrait peut-être mieux ne rien faire du tout, mais c’est pour l’exemple.

S’il y a du contenu, on l’encadre dans une magnifique div avec une couleur d’arrière plan jaune. Désolé pour le style en dur, mais pour l’exemple, cela suffira.

Testez le code court en incluant uniquement [example_enclosing_shortcode][example_enclosing_shortcode] dans l’éditeur de contenu, puis quelque chose comme [example_enclosing_shortcode] Contenu à mettre en avant ![/example_enclosing_shortcode] dans un autre bloc code court.

Code court balise affichant une boite texte jaune.
Magnifique.

Codes courts imbriqués

Que se passe-t-il si on imbrique des codes courts ? Par exemple, si on utilise [example_enclosing_shortcode][example_simple_shortcode][/example_enclosing_shortcode] ?

Il n’est pas interprété, simplement. Il faut donc utiliser la fonction do_shortcode() sur la valeur de retour de notre code court balise pour que les codes courts internes (dans $content) soient interprétés.

La fonction prend deux paramètres : le contenu dans lequel il faut appliquer les code courts ($content), et un booléen $ignore_html qui vaut false par défaut et qui permet d’ignorer les codes courts dans des balises HTML standards.

On va ajuster notre fonction de rappel comme suit:

function example_enclosing_shortcode( $atts = array(), $content = '', $tag = 'example_enclosing_shortcode' ){
    ...
    ob_start();
    ...
    return do_shortcode( ob_get_clean() );
}
Les codes courts imbriqués fonctionnent.
Les codes courts imbriqués fonctionnent.

Et que se passe-t-il quand on imbrique les mêmes codes courts ? Par exemple [example_enclosing_shortcode] Ce texte est à mettre en avant ?[example_enclosing_shortcode]Ou celui-ci ?[/example_enclosing_shortcode] ?

Les mêmes codes imbriqués fonctionnent aussi, presque.
Les mêmes codes courts imbriqués fonctionnent, presque.

Il lui manque une balise fermante, donc il considère le deuxième [example_enclosing_shortcode] vide de contenu, et retourne le message d’erreur.

Attention cependant, on voit bien ici que WordPress considère qu’il n’y a qu’une seule paire de code balise. C’est-à-dire qu’il considère qu’il n’y a qu’un seul code court avec pour contenu Ce texte est à mettre en avant ?[example_enclosing_shortcode]Ou celui-ci ?, et pas un [example_enclosing_shortcode] vide suivi du texte Ce texte est à mettre en avant ? puis un code court avec Ou celui-ci ? pour contenu.

Donc imbriquer des codes courts peut donner des résultats inattendus ! Si vous pouvez éviter, faites-le !

Codes courts dans un modèle de page

Parfois, vous aurez besoin d’intégrer le contenu d’un code court dans un modèle de page directement. Certaines extensions permettent d’ajouter des fonctionnalités utiles, comme des filtres pour vos articles par exemple, mais le code court ne peut pas forcément être mis dans le contenu de la page. Il faut ouvrir un modèle de votre thème enfant, et y insérer le code court.

En réalité, vous savez déjà comment faire ! On utilise simplement la fonction do_shortcode(), en lui passant tous les attributs dont vous avez besoin. Mais puisque do_shortcode() ne fait que filtrer son contenu et y interpréter les codes courts, il faut simplement l’afficher avec un echo.

    <?php echo do_shortcode( '[example_simple_shortcode title="Code hors contenu"]' ); ?>

Bon par contre, niveau performances un do_shortcode() est assez coûteux. Donc si vous connaissez le nom de la fonction de rappel, vous pouvez aussi l’utiliser directement, en lui passant les bons paramètres, bien entendu.

    <?php echo example_simple_shortcode( array( 'title' => 'Code hors contenu' )  ); ?>

C’est parfaitement équivalent. Attention, j’ai omis les deuxième et troisième paramètres car la déclaration de ma fonction de rappel fournit une valeur par défaut pour ces derniers.

Autres fonctions utiles

Si vous avez par hasard besoin de supprimer des codes courts enregistrés par une extension, vous pouvez le faire, en utilisant remove_shortcode( $tag ) en lui passant le nom du code à supprimer. Il faudra mettre une priorité élevée sur votre fonction de rappel hookée pour le supprimer au bon moment, c’est-à-dire juste après qu’il soit déclaré avec add_shortcode().

Vous pouvez vérifier qu’un code court existe avec shortcode_exists( string $tag ), qui vous renvoie un booléen selon si le code passé en paramètre existe.

Vous pouvez aussi vérifier qu’un certain contenu contient un code court en utilisant has_shortcode( string $content, string $tag ). La fonction prend en paramètre le contenu à vérifier et le code à chercher, et retourne un booléen selon si elle a trouvé le code dans le contenu. Simplement.

Code court et sécurité

Un code court est un outil puissant qui permet, quand on y réfléchit bien, d’exécuter du code PHP dans le contenu de vos articles. C’est puissant, mais aussi dangereux. Quand vous déclarez un code court, il est disponible pour tout le monde, y compris le simple Contributeur qui écrit un article sur votre site. Certes, il n’a pas le droit de publier, mais il peut prévisualiser, donc exécuter votre code PHP !

Soyez donc prudent avec ce que vous permettez de faire avec votre code court. Un grand pouvoir implique une grande responsabilité.

Pour résumer :

  • On déclare un code court avec add_shortcode().
  • La fonction de rappel d’un code court prends trois paramètres : $atts$content, et $tag.
  • Un code simple reçoit un $content vide. Un code de type balise reçoit le contenu entre ses balises dans $content.
  • On peut passer n’importe quel nombre d’attributs dans les crochets du code court, sous la forme clé="valeur". Un tableau avec ces attributs est passé à la fonction de rappel via $atts.
  • On utilise shortcode_atts() pour déclarer un tableau d’attributs par défaut et les fusionner avec les attributs passés dans $atts.
  • On peut imbriquer des codes courts mais il faut interpréter les codes “internes” en utilisant do_shortcode(). L’interprétation des codes courts n’est pas récursive par défaut.
  • On peut interpréter et insérer le contenu d’un code court dans un modèle de page avec echo do_shortcode().
  • On peut aussi vérifier qu’un code court existe (shortcode_exists()), le supprimer (remove_shortcode()), ou scanner du contenu pour y déterminer si un certain code court y est présent (has_shortcode()).

Les codes courts sont des outils très puissants, grâce à leur flexibilité et leurs attributs. Créer un code court est bien plus simple que de développer un bloc dynamique pour le nouvel éditeur. Certes, c’est moins joli lors de l’édition du contenu, mais c’est tout aussi puissant ! Ne vous privez pas !

PS: Cet article est un extrait de mon guide le WPCookBook, qui a pour but de vous enseigner à développer pour WordPress de façon propre et sécurisé. Si vous avez aimé cet article, alors jetez-un oeil à mon guide ! Il contient plus de 400 pages de contenu de ce type avec des explications détaillées, couvrant la majorité des besoins courants qu’un développeur WordPress puisse avoir !

Si vous voulez télécharger un extrait, inscrivez-vous ci-dessous à la newsletter !

Merci encore et à bientôt !