Stop

Hey WordPress, arrête ton char !

  • Divers

Rédigé par Olivier

19 Sep. 2023


WordPress est la plateforme qui alimente plus de 40% du Web. Elle est aimée pour sa simplicité, sa flexibilité, et sa vaste bibliothèque d’extensions. Mais si vous êtes un développeur backend et que vous êtes sensibilisé aux normes récentes de qualité (les standards PSR toussa toussa…), vous avez peut-être déjà levé un sourcil (ou deux) en jetant un œil à la structure de la base de données de WordPress, ses retours de fonctions procédurales ou ses pseudo-classes.

Du lard ou du cochon ?

Alors, commençons par les fameuses tables post_meta, term_meta et user_meta. Quelle est leur particularité ? Tous les types de données sont, comme par enchantement, des CHARs. Oui, même les entiers et les flottants y sont conservés comme des chaînes de caractères. Pourquoi faire simple quand on peut faire compliqué, n’est-ce pas ?

En réalité, afin de fournir un maximum de flexibilité sur les données, les tables post_meta, term_meta et user_meta en WordPress utilisent des champs tels que meta_key et meta_value, qui sont de type VARCHAR et LONGTEXT, respectivement. Ici, meta_value mérite toute notre attention. En effet, cette colonne stocke une grande variété de types de données en tant que texte brut, des entiers aux objets sérialisés en passant par des tableaux associatifs. Lorsqu’il s’agit d’un objet sérialisé, on a en général la chance de retrouver le typage initial (je dis bien en général, tout dépend de la qualité de l’extension ou du thème).
Mais dès lorsque que la colonne meta_value stocke une valeur unique, vous serez toujours face à un string (coquinou le WP).

Si vous êtes familier avec les normes PSR-12 et le typage strict des variables, préparez-vous à un petit choc culturel en explorant le code source de WordPress. Les fonctions et méthodes du CMS sont souvent dépourvues de typage explicite. Résultat ? C’est un peu comme faire du vélo sans mains — ça peut marcher, mais attention au virages !

Le coeur du CMS a été conçu à une époque où les meilleures pratiques en matière de typage étaient beaucoup moins répandues qu’elles ne le sont aujourd’hui. Ainsi, dans la bibliothèque de fonctions de WordPress, le typage explicite est rare. Prenez par exemple la fonction get_post_meta. Selon la documentation, elle peut retourner un tableau, une chaîne, ou même un booléen false si la meta n’est pas trouvée. Cela peut devenir un vrai casse-tête à gérer.

Pour être honnête, WordPress a fait quelques progrès en matière de modernisation de son code. Cependant, il a encore du mal à rattraper des frameworks ou CMS plus récents, qui ont intégré les meilleures pratiques de développement dès le départ. La faute au souhait de garder une rétro-compatibilité.

Les problématiques posées

La conséquence ? D’abord, cela affecte les performances. Chaque requête doit convertir ces CHARs en types de données appropriés, ce qui prend du temps. Cela augmente la charge cognitive pour le développeur car il manipule des données dont il ne sait pas exactement ce dont il s’agit (non une chaine vide n’équivaut pas à un false). Enfin, cela rend le débugguage beaucoup plus complexe car on ne pourra pas déterminer que l’erreur provient d’un format de donnée non attendu.

Prenons un exemple simple. Imaginons que vous vouliez récupérer un identifiant de produit stocké dans post_meta pour faire une opération mathématique. Vous utilisez get_post_meta() et vous vous retrouvez avec une valeur de type string. Avant toute opération, vous devrez explicitement convertir cette chaîne en entier. Si cette action est répétée à plusieurs reprises, les microsecondes perdues s’accumulent et peuvent affecter les performances globales, surtout sur un site à fort trafic.

On a eu dernièrement un exemple sur un développement qui consistait en la mise en place d’un compteur du nombre de vues d’articles. La données de comptabilisation était stockée sous forme de post meta. La requête SQL pour récupérer les 5 articles les plus vus était la suivante :

SELECT ID
FROM {$wpdb->posts}
JOIN {$wpdb->prefix}postmeta ON {$wpdb->prefix}postmeta.post_id = {$wpdb->posts}.id
WHERE meta_key = 'views'
ORDER BY meta_value DESC
LIMIT %d;

Le souci, c’est que lorsqu’on débuggue le nombre de vues renvoyé par la requête, on se retrouvait avec ce tableau incohérent :

array(
    9,
    85,
    59,
    51,
    48
);

Et oui, on peut pas demander à MySQL de traiter de la chaine de caractère comme des valeurs numériques. Seule solution, caster l’ordonnancement avec ORDER BY CAST(meta_value AS SIGNED) DESC ou simuler une opération en utilisant ORDER BY meta_value + 0 DESC. On va pas se le cacher, c’est de la bidouille 🙂

Ensuite, étant donné que WordPress ne retourne pas de types de données stricts, les erreurs peuvent passer inaperçues pendant un certain temps. Par exemple, si une fonction attend un tableau et reçoit une chaîne de caractères, elle pourrait ne pas échouer immédiatement, mais plutôt plus tard dans le processus, rendant le débogage plus complexe.

Quelles solutions ?

Tout d’abord, pour mieux contrôler le typage des données retournées par les fonctions WordPress natives, on peut développer des « wrappers » ou fonctions enveloppes qui s’occupent de la conversion de types. Par exemple, un wrapper pour get_post_meta pourrait toujours retourner un type de données précis, évitant ainsi les ambiguïtés. Il est évident que cela suppose un travail conséquent et on ne résoud en rien le problèmes de performances liés à la conversion du format des données.

En l’absence d’un typage strict, l’utilisation d’annotations et de DocBlocks peut s’avérer très utile. Bien que cela ne remplace pas un véritable contrôle du typage, cela peut au moins servir de documentation pour les développeurs et faciliter l’intégration avec des outils de développement qui reconnaissent ces commentaires.

L’utilisation d’un ORM (Object-Relational Mapping) comme Eloquent pourrait être une solution efficace. Cela permet de définir clairement les types de données attendus pour chaque propriété de l’objet. Cela suppose tout de même une charge de travail importante car vous devrez créer les modèles de données pour chaque entités (Il existe toutefois des solutions prêtes à l’emploi comme Corcel).

Également, des outils comme Psalm ou PHPStan peuvent analyser votre code pour y détecter les problèmes de typage. Ils n’ajoutent pas de typage strict au code source de WordPress, mais ils peuvent aider à identifier les zones à risque dans notre propre code.

Enfin, L’une des solutions les plus radicales, mais également les plus efficaces, pour contrer le manque de typage dans WordPress est la création de vos propres tables de bases de données. En prenant cette voie, vous pouvez définir explicitement le schéma, les relations, les index et, surtout, les types de données pour chaque colonne. Cela permet d’éviter les ambiguïtés et les conversions de types, rendant ainsi le développement plus rapide et plus sûr.

Cependant, il y a un hic. Actuellement, WordPress ne propose pas de standard clair pour la création et la gestion de tables personnalisées. Chaque développeur ou agence fait un peu comme bon lui semble. Ce genre de fragmentation est précisément ce que l’on souhaite éviter dans un écosystème logiciel.

C’est ici qu’un standard WordPress pour la gestion des tables de bases de données personnalisées pourrait être une véritable bouffée d’air frais. Un tel standard définirait des meilleures pratiques et fournirait peut-être même des outils de génération et de migration de tables, similaire à ce que propose Laravel avec ses migrations. Cela rendrait le processus plus uniforme, plus sûr et plus facile à gérer pour tous les développeurs, novices comme experts. On pourrait étendre la classe WP_List_Table responsable de générer le tableau de données au sein de l’admin pour qu’elle soit plus simple à utiliser avec des tables personnalisées.

Pour conclure…

Au sein d’AmphiBee, on est fan de WordPress mais être fan ne nous rend pas aveugle pour autant. Comme nous l’avons vu, il traîne aussi quelques casseroles en termes de typage. Entre structures de bases de données permissives et fonctions aux retours imprévisibles, la vie du développeur est loin d’être un long fleuve tranquille. Quand il s’agit de faire du webmastering, ce n’est pas un souci mais dès lors qu’on entre dans des développements complexes et de la gestion de flux de données, ça peut devenir un vrai casse-tête.

Pour cette raison, nous avons intégrés très tôt des solutions provenant de l’écosystème Laravel pour améliorer notamment cette problématique de typage de données (et mon petit doigt me dit qu’on est pas à l’abris de dévoiler quelque chose à ce sujet prochainement…)

La phase d’amélioration de WordPress est actuellement focalisée sur la partie javascript avec Gutenberg. Cette modernisation va dans le bon sens et on aimerait une roadmap pour enfin s’attaquer aux conventions de codage et à l’architecture technique.

Il faut toutefois ne pas négliger le travail immense de la communauté. Cet investissement permet à un grand nombre de disposer d’un site web très simplement et à faire vivre de nombreuses agences comme nous.

Crédit photos : https://unsplash.com/fr/photos/BuR0VODxAOU

D'autres articles pouvant vous plaire !

Laravel VS Symfony

Laravel vs Symfony : Comparatif Détaillé

21 Août. 2024
Laravel e-commerce

Financez la création de votre site internet grâce à l’ADEN

30 Oct. 2023
Réparation d'un site web

Comment créer un site WordPress sur mesure ?

02 Avr. 2024