Les shortcodes ont été déclarés obsolètes à chaque nouvelle version de l'éditeur et ils sont toujours là, pour une raison simple : ils fonctionnent partout, dans un contenu, dans un widget, dans un gabarit, dans un courriel généré, et ils survivent aux changements de thème comme aux changements d'éditeur. Un shortcode WordPress bien écrit reste l'un des moyens les plus robustes de rendre un composant réutilisable. Encore faut il l'écrire correctement, ce qui suppose trois choses trop souvent négligées : des attributs déclarés avec des valeurs par défaut, des valeurs validées avant usage, et un rendu intégralement échappé selon le contexte de sortie.
Ce qu'est vraiment un shortcode aujourd'hui
Le mécanisme est ancien et son fonctionnement exact détermine une bonne partie des précautions à prendre. Ces considérations rejoignent celles que nous développons sur la manière de bien choisir une extension pour WordPress.
Un remplacement dans le contenu
Au moment de l'affichage, le contenu est parcouru à la recherche des motifs déclarés, et chaque occurrence est remplacée par ce que retourne la fonction associée. Ce traitement intervient tard dans la chaîne, après les filtres de mise en forme automatique, ce qui explique certains comportements surprenants avec les retours à la ligne. Comprendre ce point évite des heures de recherche sur des paragraphes vides apparaissant autour d'un composant. La règle pratique consiste à écrire le motif seul sur sa ligne dans l'éditeur et à éviter les retours à la ligne superflus dans le rendu produit.
Retourner et ne jamais afficher
La fonction associée doit retourner une chaîne, jamais l'afficher directement. Un affichage direct produit le contenu au moment de l'exécution du remplacement, donc avant le reste de la page, ce qui déplace le composant en haut du contenu. C'est le défaut le plus fréquent et le plus déroutant, et il se corrige en capturant la sortie dans un tampon quand le rendu est écrit sous forme de gabarit plutôt que de concaténation. Cette capture par tampon est d'ailleurs la façon la plus lisible d'écrire un rendu un peu long, la concaténation de balises devenant vite illisible.
Le cas des attributs et du contenu encadré
Un shortcode peut recevoir des attributs et, dans sa forme encadrante, un contenu placé entre une balise ouvrante et une balise fermante. La fonction reçoit ces deux éléments séparément, plus le nom du motif appelé, ce qui permet à une même fonction de servir plusieurs motifs. Cette forme encadrante est particulièrement utile pour les composants de mise en page, et elle impose un traitement spécifique du contenu reçu, qui peut lui même contenir d'autres motifs à traiter. Il faut également prévoir le cas où ce contenu est vide, forme que les rédacteurs produisent régulièrement sans intention particulière.
Où le déclarer
Un shortcode utilisé dans les contenus doit vivre dans une extension et non dans le fichier de fonctions du thème. La raison est simple : le jour où le thème change, tous les contenus du site afficheront le texte brut du motif au lieu du composant, sur des centaines de pages. Cette règle vaut pour tout ce qui touche au contenu, et elle est enfreinte à peu près systématiquement sur les sites que nous reprenons. Une extension d'une trentaine de lignes suffit à héberger tous les composants du site, et elle coûte moins cher à créer qu'une seule intervention de réparation.
La cohabitation avec l'éditeur de blocs
L'éditeur moderne propose un bloc dédié permettant d'insérer un shortcode, ce qui garantit la compatibilité. Il est également possible d'enregistrer un bloc dont le rendu est produit côté serveur par la même fonction, ce qui offre une interface de saisie confortable tout en conservant le shortcode pour les usages hors éditeur. Cette double exposition est le meilleur compromis actuel, et elle coûte peu une fois la fonction de rendu correctement isolée. Le bloc apporte au rédacteur des champs et des menus déroulants, ce qui supprime les fautes de frappe dans les noms d'attributs.

Déclarer et traiter les attributs
Le traitement des attributs concentre l'essentiel des défauts observés. Une fonction qui lit directement les valeurs reçues sans les fusionner avec des valeurs par défaut produira une erreur dès qu'un attribut est omis.
Fusionner avec des valeurs par défaut
La fonction dédiée à cet usage prend un tableau de valeurs par défaut et le tableau reçu, et retourne la combinaison, en ignorant les attributs non déclarés. Ce passage est obligatoire, non seulement pour éviter les erreurs sur les clés absentes mais aussi pour empêcher qu'un attribut inattendu ne se retrouve dans le traitement. Le tableau de valeurs par défaut sert en outre de documentation du composant, ce qui n'est pas son moindre mérite. Une valeur par défaut bien choisie permet en outre d'utiliser le composant sans aucun attribut dans le cas le plus courant, ce que les rédacteurs apprécient.
Les attributs sont toujours des chaînes
Toute valeur reçue est une chaîne de caractères, y compris celles qui ressemblent à des nombres ou à des booléens. Une valeur destinée à être utilisée comme entier doit être convertie explicitement après vérification, et une valeur booléenne doit être comparée à une liste de représentations acceptées. Traiter une chaîne comme un booléen donne un résultat vrai pour toute valeur non vide, y compris pour un attribut valant faux, erreur classique et parfaitement silencieuse. La liste des représentations à accepter doit inclure les formes que les rédacteurs écrivent spontanément, en français comme en anglais.
Valider par liste plutôt que par exclusion
Un attribut désignant un alignement, une taille ou un style doit être comparé à une liste de valeurs autorisées, avec repli sur la valeur par défaut en cas de correspondance manquante. Cette approche garantit qu'aucune valeur inattendue n'atteint le rendu, ce qui règle du même coup une bonne partie des questions d'échappement. Elle rend le composant prévisible et facilite l'écriture de la feuille de style associée. Elle protège également des fautes de frappe, qui produisent alors le comportement par défaut plutôt qu'un affichage cassé.
Les attributs de nom d'élément
Un attribut désignant un identifiant de contenu ou une catégorie doit être converti en entier puis vérifié quant à l'existence de l'élément désigné. Un identifiant inexistant ne doit pas produire d'erreur mais un rendu vide ou un message discret. Il faut également garder à l'esprit qu'un contenu privé ou en brouillon ne doit pas être affiché à un visiteur non autorisé, contrôle que le composant doit assurer lui même puisque personne d'autre ne le fera. La vérification du statut du contenu et des droits de l'utilisateur courant tient en deux lignes et évite une fuite d'information parfaitement involontaire.
La casse des noms d'attributs
Les noms d'attributs sont ramenés en minuscules par le mécanisme de traitement, ce qui signifie qu'un attribut déclaré avec une majuscule ne sera jamais trouvé. Ce détail produit des composants qui ignorent silencieusement une partie de leur configuration, et il explique un certain nombre de comportements inexpliqués sur des shortcodes repris d'anciens projets. Toutes les clés doivent donc être écrites en minuscules, sans exception. La même prudence vaut pour les tirets et les caractères de soulignement, dont l'usage doit rester cohérent sur l'ensemble des composants d'un site.
Documenter les attributs
Un bloc de commentaire en tête de la fonction, listant chaque attribut, son type, sa valeur par défaut et un exemple d'utilisation, transforme un composant obscur en outil utilisable. Cette documentation prend cinq minutes et évite que la personne qui rédige n'ait à lire le code pour savoir ce qu'elle peut passer. Sur un site où plusieurs personnes rédigent, elle mérite d'être reprise dans une page d'aide accessible depuis l'administration. Quelques exemples copiables valent mieux qu'une longue explication, l'usage se comprenant plus vite par l'exemple que par la description.
| Type d'attribut | Traitement | Comportement si invalide |
|---|---|---|
| Texte libre | Échappement au rendu | Affiché échappé |
| Nombre | Conversion après vérification | Valeur par défaut |
| Booléen | Comparaison à une liste | Valeur par défaut |
| Choix parmi des valeurs | Liste autorisée | Valeur par défaut |
| Identifiant de contenu | Entier puis contrôle d'existence | Rendu vide |
| Adresse web | Validation du protocole | Lien supprimé |
| Classe CSS | Nettoyage des caractères autorisés | Classe ignorée |
Produire un rendu sûr
Le rendu est la partie visible du composant et celle où les défauts de sécurité se concrétisent. Le principe directeur est simple : rien ne sort sans avoir été traité selon son contexte.
Échapper selon le contexte
Une valeur placée dans le corps du document, dans un attribut, dans une adresse ou dans un bloc de script ne demande pas le même traitement. WordPress fournit une fonction par contexte, et leur emploi doit être systématique plutôt que réservé aux valeurs jugées suspectes. Ce raisonnement est développé dans notre article sur la manière d'échapper correctement ses sorties en PHP.
Le contenu encadré
Le contenu placé entre les balises ouvrante et fermante peut légitimement contenir du HTML, ce qui interdit de l'échapper purement et simplement. Il doit être passé par le mécanisme de nettoyage de WordPress, qui ne conserve que les balises et attributs autorisés pour le rôle de l'utilisateur courant. C'est exactement la fonction pour laquelle ce mécanisme existe, et le réécrire soi même par des expressions régulières est une mauvaise idée aux conséquences durables. Le jeu de balises autorisées peut être restreint au strict nécessaire pour le composant, ce qui est préférable à l'emploi du jeu par défaut.
Traiter les motifs imbriqués
Le contenu encadré peut contenir d'autres motifs, qui ne seront pas traités automatiquement. Il faut appliquer explicitement la fonction de traitement à ce contenu pour permettre l'imbrication. Cette opération doit intervenir avant le nettoyage, et non après, faute de quoi le rendu produit par les composants imbriqués sera lui même filtré une seconde fois, ce qui retire parfois des éléments légitimes. L'ordre des opérations est ici la seule chose qui compte, et une inversion produit des symptômes difficiles à relier à leur cause.
Séparer le rendu du traitement
La fonction du shortcode doit se limiter à valider les attributs et à appeler une fonction de rendu séparée, qui produit la chaîne. Cette séparation permet de réutiliser le rendu ailleurs, dans un bloc, dans un gabarit ou dans une réponse d'interface de programmation, sans dupliquer le code. Elle rend également le rendu testable indépendamment, ce qui est la seule façon d'écrire une vérification automatique sur un composant. Cette fonction de rendu doit recevoir des paramètres déjà validés et se contenter de produire la chaîne, sans effectuer elle même de contrôle.
Charger les styles au bon moment
Une feuille de style chargée sur toutes les pages pour un composant présent sur trois d'entre elles est du gaspillage. Le chargement conditionnel, déclenché depuis la fonction de rendu, résout ce point proprement sur les versions récentes de WordPress, qui savent placer une ressource même lorsque l'appel intervient tard dans la génération. Sur les installations plus anciennes, une détection en amont dans le contenu reste nécessaire. Cette détection consiste simplement à chercher le motif dans le contenu avant la génération de l'en-tête de page, opération peu coûteuse.
Mettre le rendu en cache
Un composant effectuant une requête coûteuse ou un appel distant doit mettre son résultat en cache, avec une durée de vie adaptée et une clé incluant les attributs. Sans cela, une page contenant dix occurrences du composant déclenche dix traitements identiques. Cette mise en cache est particulièrement importante lorsque le composant interroge un service externe, cas où l'absence de cache rend la page dépendante de la disponibilité de ce service. Un délai maximal court sur l'appel distant complète utilement ce dispositif, afin qu'une lenteur du service ne bloque jamais l'affichage de la page.
Défauts constatés sur des composants écrits sur mesure. Les deux premiers produisent respectivement des erreurs visibles et des vulnérabilités exploitables.
Maintenir et faire évoluer
Un shortcode inséré dans des centaines de contenus devient un engagement de longue durée, ce qui impose quelques précautions au moment de sa conception.
Choisir un nom préfixé et durable
Le nom du motif doit être préfixé pour éviter toute collision avec une extension installée ultérieurement, et il ne pourra plus être changé sans réécrire tous les contenus. Un nom court, explicite et préfixé du nom du site ou de l'extension évite ces deux écueils. Une collision de nom produit un comportement imprévisible, le dernier motif enregistré l'emportant, ce qui rend le diagnostic particulièrement pénible. Un préfixe de trois ou quatre lettres suffit à écarter ce risque de façon définitive.
Ne jamais supprimer un shortcode
La désactivation de l'extension qui déclare un motif fait apparaître le texte brut de celui ci dans tous les contenus concernés. C'est le principal reproche fait à ce mécanisme, et il se gère : un composant devenu inutile doit être conservé avec un rendu vide plutôt que supprimé, le temps que les contenus soient nettoyés. Ce nettoyage se fait par une recherche et un remplacement en base, opération à mener avec une sauvegarde préalable. Il vaut mieux la mener en plusieurs passes ciblées qu'en un seul remplacement massif, afin de pouvoir vérifier le résultat au fur et à mesure.
Prévoir la compatibilité ascendante
L'ajout d'un attribut ne pose aucun problème tant qu'il dispose d'une valeur par défaut cohérente avec le comportement antérieur. La suppression ou le changement de signification d'un attribut existant, en revanche, modifie l'affichage de contenus déjà publiés sans que personne ne s'en aperçoive. Ces évolutions demandent un recensement préalable des usages, qu'une simple recherche en base fournit en quelques secondes. Le nombre de contenus concernés détermine ensuite s'il faut prévoir une compatibilité ou accepter une reprise manuelle.
Tester le rendu
Une poignée de vérifications comparant le rendu attendu au rendu obtenu, pour les cas nominaux et pour les attributs invalides, suffit à sécuriser les évolutions. La séparation entre traitement et rendu, évoquée plus haut, est ce qui rend ces tests possibles sans monter un environnement complet. Cet effort se justifie dès qu'un composant est utilisé sur plus d'une dizaine de pages. En dessous de ce seuil, une vérification visuelle après modification reste parfaitement suffisante.
Surveiller les performances
Un composant apparemment anodin peut peser lourd s'il est présent sur de nombreuses pages et effectue une requête à chaque affichage. Le temps de génération des pages qui le contiennent, comparé à celui des pages qui ne le contiennent pas, donne la réponse en quelques minutes. Cette comparaison est le moyen le plus simple d'identifier un composant coûteux parmi plusieurs, sans avoir à instrumenter le code.
Envisager la bibliothèque plutôt que le sur mesure
Pour des besoins très courants, boutons, encadrés, colonnes, onglets, une extension établie fournit un ensemble complet et maintenu, ce qui évite d'écrire et d'entretenir vingt composants. Cette voie est décrite dans notre article consacré à Shortcodes Ultimate. Le sur mesure garde tout son sens pour ce qui est propre au site, et il vaut mieux le réserver à ces cas plutôt que de réécrire ce qui existe déjà. La frontière se trace assez bien en se demandant si le besoin serait formulé à l'identique par un autre site du même secteur, auquel cas l'extension existante fera l'affaire.
💬 0 commentaires
✍️ Laisser un commentaire
Créez un compte gratuit ou connectez-vous pour commenter.