Améliorer le code WordPress avec PHP moderne
Publié: 2022-03-10WordPress est né il y a quinze ans, et parce qu'il a historiquement conservé la rétrocompatibilité, les nouvelles versions de son code ne pouvaient pas tirer pleinement parti des dernières fonctionnalités offertes par les nouvelles versions de PHP. Alors que la dernière version de PHP est la 7.3.2, WordPress offre toujours un support jusqu'à PHP 5.2.4.
Mais ces jours seront bientôt révolus ! WordPress mettra à jour sa prise en charge minimale de la version PHP, passant à PHP 5.6 en avril 2019 et PHP 7 en décembre 2019 (si tout se passe comme prévu). Nous pouvons alors enfin commencer à utiliser les capacités de programmation impérative de PHP sans craindre de casser les sites de nos clients. Hourra!
Parce que les quinze années de code fonctionnel de WordPress ont influencé la façon dont les développeurs ont construit avec WordPress, nos sites, thèmes et plugins peuvent être jonchés de code moins qu'optimal qui peut volontiers recevoir une mise à niveau.
Cet article est composé de deux parties :
- Nouvelles fonctionnalités les plus pertinentes
D'autres fonctionnalités ont été ajoutées aux versions PHP 5.3, 5.4, 5.5, 5.6 et 7.0 (notez qu'il n'y a pas de PHP 6) et nous allons explorer les plus pertinentes. - Créer de meilleurs logiciels
Nous examinerons de plus près ces fonctionnalités et comment elles peuvent nous aider à créer de meilleurs logiciels.
Commençons par explorer les "nouvelles" fonctionnalités de PHP.
Classes, OOP, SOLID et modèles de conception
Des classes et des objets ont été ajoutés à PHP 5, donc WordPress utilise déjà ces fonctionnalités, mais pas de manière très extensive ou exhaustive : le paradigme du codage dans WordPress est principalement la programmation fonctionnelle (effectuer des calculs en appelant des fonctions dépourvues d'état de l'application) au lieu d'objet -programmation orientée (POO) (effectuer des calculs en manipulant l'état des objets). Par conséquent, je décris également les classes et les objets et comment les utiliser via la POO.
La POO est idéale pour produire des applications modulaires : les classes permettent la création de composants, chacun pouvant implémenter une fonctionnalité spécifique et interagir avec d'autres composants, et peut fournir une personnalisation grâce à ses propriétés encapsulées et à son héritage, permettant un degré élevé de réutilisation du code. Par conséquent, l'application est moins chère à tester et à entretenir, car les fonctionnalités individuelles peuvent être isolées de l'application et traitées par elles-mêmes ; il y a aussi un gain de productivité puisque le développeur peut utiliser des composants déjà développés et éviter de réinventer la roue pour chaque application.
Une classe a des propriétés et des fonctions, qui peuvent être rendues visibles en utilisant private
(accessible uniquement depuis la classe de définition), protected
(accessible depuis la classe de définition et ses classes ancêtre et héritantes) et public
(accessible de partout). Depuis une fonction, nous pouvons accéder aux propriétés de la classe en ajoutant à leurs noms $this->
:
class Person { protected $name; public function __construct($name) { $this->name = $name; } public function getIntroduction() { return sprintf( __('My name is %s'), $this->name ); } }
Une classe est instanciée dans un objet via le new
mot-clé, après quoi nous pouvons accéder à ses propriétés et fonctions via ->
:
$person = new Person('Pedro'); echo $person->getIntroduction(); // This prints "My name is Pedro"
Une classe qui hérite peut remplacer les public
et protected
de ses classes ancêtres et accéder aux fonctions ancêtres en les ajoutant au début avec parent::
:
class WorkerPerson extends Person { protected $occupation; public function __construct($name, $occupation) { parent::__construct($name); $this->occupation = $occupation; } public function getIntroduction() { return sprintf( __('%s and my occupation is %s'), parent::getIntroduction(), $this->occupation ); } } $worker = new WorkerPerson('Pedro', 'web development'); echo $worker->getIntroduction(); // This prints "My name is Pedro and my occupation is web development"
Une méthode peut être rendue abstract
, ce qui signifie qu'elle doit être implémentée par une classe qui hérite. Une classe contenant une méthode abstract
doit être rendue abstract
elle-même, ce qui signifie qu'elle ne peut pas être instanciée ; seule la classe implémentant la méthode abstraite peut être instanciée :
abstract class Person { abstract public function getName(); public function getIntroduction() { return sprintf( __('My name is %s'), $this->getName() ); } } // Person cannot be instantiated class Manuel extends Person { public function getName() { return 'Manuel'; } } // Manuel can be instantiated $manuel = new Manuel();
Les classes peuvent également définir des méthodes et des propriétés static
, qui vivent sous la classe elle-même et non sous une instanciation de la classe en tant qu'objet. Ceux-ci sont accessibles via self::
depuis l'intérieur de la classe, et via le nom de la classe + ::
depuis l'extérieur :
class Factory { protected static $instances = []; public static function registerInstance($handle, $instance) { self::$instances[$handle] = $instance; } public static function getInstance($handle) { return self::$instances[$handle]; } } $engine = Factory::getInstance('Engine');
Pour tirer le meilleur parti de la POO, nous pouvons utiliser les principes SOLID pour établir une base solide mais facilement personnalisable pour l'application, et concevoir des modèles pour résoudre des problèmes spécifiques de manière éprouvée. Les modèles de conception sont standardisés et bien documentés, permettant aux développeurs de comprendre comment les différents composants de l'application sont liés les uns aux autres et fournissent un moyen de structurer l'application de manière ordonnée, ce qui permet d'éviter l'utilisation de variables globales (telles que global $wpdb
) qui polluent l'environnement mondial.
Espaces de noms
Les espaces de noms ont été ajoutés à PHP 5.3, ils sont donc actuellement totalement absents du noyau WordPress.
Les espaces de noms permettent d'organiser la base de code de manière structurelle pour éviter les conflits lorsque différents éléments portent le même nom - d'une manière similaire aux répertoires du système d'exploitation qui permettent d'avoir différents fichiers portant le même nom tant qu'ils sont stockés dans des répertoires différents. Les espaces de noms font la même astuce d'encapsulation pour les éléments PHP (tels que les classes, les traits et les interfaces) en évitant les collisions lorsque différents éléments portent le même nom en les plaçant sur des espaces de noms différents.
Les espaces de noms sont indispensables lors de l'interaction avec des bibliothèques tierces, car nous ne pouvons pas contrôler la manière dont leurs éléments seront nommés, ce qui entraîne des collisions potentielles lors de l'utilisation de noms standard tels que "Fichier", "Logger" ou "Uploader" pour nos éléments. De plus, même au sein d'un même projet, les espaces de noms empêchent les noms de classe de devenir extrêmement longs afin d'éviter les conflits avec d'autres classes, ce qui pourrait entraîner des noms tels que "MyProject_Controller_FileUpload".
Les espaces de noms sont définis à l'aide du mot-clé namespace
(placé sur la ligne immédiatement après l'ouverture <?php
) et peuvent s'étendre sur plusieurs niveaux ou sous-espaces de noms (similaire à avoir plusieurs sous-répertoires où placer un fichier), qui sont séparés par un \
:
<?php namespace CoolSoft\ImageResizer\Controllers; class ImageUpload { }
Pour accéder à la classe ci-dessus, nous devons qualifier entièrement son nom, y compris son espace de noms (et commençant par \
):
$imageUpload = new \CoolSoft\ImageResizer\Controllers\ImageUpload();
Ou nous pouvons également importer la classe dans le contexte actuel, après quoi nous pouvons référencer directement la classe par son nom :
use CoolSoft\ImageResizer\Controllers\ImageUpload; $imageUpload = new ImageUpload();
En nommant les espaces de noms selon les conventions établies, nous pouvons obtenir des avantages supplémentaires. Par exemple, en suivant la recommandation des normes PHP PSR-4, l'application peut utiliser le mécanisme de chargement automatique de Composer pour charger les fichiers, réduisant ainsi la complexité et ajoutant une interopérabilité sans friction entre les dépendances. Cette convention établit d'inclure le nom du fournisseur (par exemple, le nom de l'entreprise) comme sous-espace de noms supérieur, éventuellement suivi du nom du package, et seulement ensuite suivi d'une structure interne dans laquelle chaque sous-espace de noms correspond à un répertoire portant le même nom. Le résultat mappe 1 à 1 l'emplacement physique du fichier dans le lecteur avec l'espace de noms de l'élément défini dans le fichier.
Traits
Des traits ont été ajoutés à PHP 5.4, ils sont donc actuellement totalement absents du noyau WordPress.
PHP prend en charge l'héritage unique, de sorte qu'une sous-classe est dérivée d'une seule classe parente et non de plusieurs. Par conséquent, les classes qui ne s'étendent pas les unes aux autres ne peuvent pas réutiliser le code via l'héritage de classe. Les traits sont un mécanisme qui permet la composition horizontale du comportement, permettant de réutiliser le code parmi les classes qui vivent dans différentes hiérarchies de classes.
Un trait est similaire à une classe, cependant, il ne peut pas être instancié seul. Au lieu de cela, le code défini à l'intérieur d'un trait peut être considéré comme étant "copié et collé" dans la classe de composition au moment de la compilation.
Un trait est défini à l'aide du mot-clé trait
, après quoi il peut être importé dans n'importe quelle classe via le mot-clé use
. Dans l'exemple ci-dessous, deux classes Person
et Shop
totalement indépendantes peuvent réutiliser le même code via un trait Addressable
:
trait Addressable { protected $address; public function getAddress() { return $this->address; } public function setAddress($address) { $this->address = $address; } } class Person { use Addressable; } class Shop { use Addressable; } $person = new Person('Juan Carlos'); $person->setAddress('Obelisco, Buenos Aires');
Une classe peut aussi composer plus d'un trait :
trait Exportable { public class exportToCSV($filename) { // Iterate all properties and export them to a CSV file } } class Person { use Addressable, Exportable; }
Les traits peuvent également être composés d'autres traits, définir des méthodes abstraites et offrir un mécanisme de résolution de conflit lorsque deux ou plusieurs traits composés ont le même nom de fonction, entre autres caractéristiques.
Interfaces
Des interfaces ont été ajoutées à PHP 5, donc WordPress utilise déjà cette fonctionnalité, mais de manière extrêmement parcimonieuse : le noyau comprend moins de dix interfaces au total !
Les interfaces permettent de créer du code qui spécifie quelles méthodes doivent être implémentées, sans avoir à définir comment ces méthodes sont réellement implémentées. Ils sont utiles pour définir des contrats entre les composants, ce qui conduit à une meilleure modularité et maintenabilité de l'application : une classe implémentant une interface peut être une boîte noire de code, et tant que les signatures des fonctions dans l'interface ne changent pas, la le code peut être mis à jour à volonté sans produire de modifications majeures, ce qui peut aider à prévenir l'accumulation de dette technique. De plus, ils peuvent aider à réduire la dépendance vis-à-vis d'un fournisseur, en permettant de remplacer l'implémentation d'une interface par celle d'un autre fournisseur. Par conséquent, il est impératif de coder l'application par rapport aux interfaces plutôt qu'aux implémentations (et de définir quelles sont les implémentations réelles via l'injection de dépendances).
Les interfaces sont définies à l'aide du mot-clé interface
, et doivent lister uniquement la signature de ses méthodes (c'est-à-dire sans avoir défini leur contenu), qui doivent avoir une visibilité public
(par défaut, l'ajout d'aucun mot-clé de visibilité la rend également publique) :
interface FileStorage { function save($filename, $contents); function readContents($filename); }
Une classe définit qu'elle implémente l'interface via le mot clé implements
:
class LocalDriveFileStorage implements FileStorage { function save($filename, $contents) { // Implement logic } function readContents($filename) { // Implement logic } }
Une classe peut implémenter plus d'une interface, en les séparant par ,
:
interface AWSService { function getRegion(); } class S3FileStorage implements FileStorage, AWSService { function save($filename, $contents) { // Implement logic } function readContents($filename) { // Implement logic } function getRegion() { return 'us-east-1'; } }
Puisqu'une interface déclare l'intention de ce qu'un composant est censé faire, il est extrêmement important de nommer les interfaces de manière appropriée.
Fermetures
Des fermetures ont été ajoutées à PHP 5.3, elles sont donc actuellement totalement absentes du noyau WordPress.
Closures est un mécanisme d'implémentation de fonctions anonymes, qui permet de désencombrer l'espace de noms global des fonctions à usage unique (ou rarement utilisées). Techniquement parlant, les fermetures sont des instances de la classe Closure
, cependant, dans la pratique, nous pouvons très probablement ignorer parfaitement ce fait sans aucun mal.
Avant les fermetures, à chaque passage d'une fonction en argument à une autre fonction, nous devions définir la fonction à l'avance et passer son nom en argument :
function duplicate($price) { return $price*2; } $touristPrices = array_map('duplicate', $localPrices);
Avec les fermetures, une fonction anonyme (c'est-à-dire sans nom) peut déjà être passée directement en paramètre :
$touristPrices = array_map(function($price) { return $price*2; }, $localPrices);
Les fermetures peuvent importer des variables dans son contexte via le mot-clé use
:
$factor = 2; $touristPrices = array_map(function($price) use($factor) { return $price*$factor; }, $localPrices);
Générateurs
Des générateurs ont été ajoutés à PHP 5.5, ils sont donc actuellement totalement absents du noyau WordPress.
Les générateurs permettent d'implémenter facilement des itérateurs simples. Un générateur permet d'écrire du code qui utilise foreach
pour itérer sur un ensemble de données sans avoir besoin de construire un tableau en mémoire. Une fonction génératrice est identique à une fonction normale, sauf qu'au lieu de revenir une fois, elle peut yield
autant de fois que nécessaire pour fournir les valeurs à itérer.
function xrange($start, $limit, $step = 1) { for ($i = $start; $i <= $limit; $i += $step) { yield $i; } } foreach (xrange(1, 9, 2) as $number) { echo "$number "; } // This prints: 1 3 5 7 9
Déclarations des arguments et des types de retour
Différentes déclarations de type d'argument ont été introduites dans différentes versions de PHP : WordPress est déjà capable de déclarer des interfaces et des tableaux (ce qu'il ne fait pas : j'ai à peine trouvé une instance d'une fonction déclarant un tableau comme paramètre dans le noyau, et aucune interface), et bientôt pouvoir déclarer des callables (ajouté en PHP 5.4) et des types scalaires : bool, float, int et string (ajouté en PHP 7.0). Les déclarations de type de retour ont été ajoutées à PHP 7.0.
Les déclarations de type d'argument permettent aux fonctions de déclarer de quel type spécifique doit être un argument. La validation est exécutée au moment de l'appel, levant une exception si le type de l'argument n'est pas celui déclaré. Les déclarations de type de retour sont le même concept, cependant, elles spécifient le type de valeur qui sera renvoyé par la fonction. Les déclarations de type sont utiles pour faciliter la compréhension de l'intention de la fonction et pour éviter que des erreurs d'exécution ne reçoivent ou ne renvoient un type inattendu.
Le type d'argument est déclaré avant le nom de la variable d'argument et le type de retour est déclaré après les arguments, précédé de :
:
function foo(boolean $bar): int { }
Les déclarations de type d'argument scalaire ont deux options : coercitives et strictes. En mode coercitif, si le mauvais type est passé en paramètre, il sera converti dans le bon type. Par exemple, une fonction qui reçoit un entier pour un paramètre qui attend une chaîne obtiendra une variable de type chaîne. En mode strict, seule une variable du type exact de déclaration sera acceptée.
Le mode coercitif est le mode par défaut. Pour activer le mode strict, nous devons ajouter une instruction declare
utilisée avec la déclaration strict_types
:

declare(strict_types=1); function foo(boolean $bar) { }
Nouvelle syntaxe et opérateurs
WordPress peut déjà identifier des listes d'arguments de longueur variable grâce à la fonction func_num_args
. À partir de PHP 5.6, nous pouvons utiliser le jeton ...
pour indiquer que la fonction accepte un nombre variable d'arguments, et ces arguments seront passés dans la variable donnée sous forme de tableau :
function sum(...$numbers) { $sum = 0; foreach ($numbers as $number) { $sum += $number; } return $sum; }
À partir de PHP 5.6, les constantes peuvent impliquer des expressions scalaires impliquant des littéraux numériques et des chaînes au lieu de simples valeurs statiques, ainsi que des tableaux :
const SUM = 37 + 2; // A scalar expression const LETTERS = ['a', 'b', 'c']; // An array
À partir de PHP 7.0, les tableaux peuvent également être définis à l'aide de define
:
define('LETTERS', ['a', 'b', 'c']);
PHP 7.0 a ajouté quelques nouveaux opérateurs : l'opérateur Null coalescing ( ??
) et l'opérateur Spaceship ( <=>
).
L'opérateur de coalescence Null ??
est du sucre syntaxique pour le cas courant où il faut utiliser un ternaire en conjonction avec isset(). Il renvoie son premier opérande s'il existe et n'est pas NULL ; sinon, il renvoie son deuxième opérande.
$username = $_GET['user'] ?? 'nobody'; // This is equivalent to: // $username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
L'opérateur Spaceship <=>
est utilisé pour comparer deux expressions, renvoyant -1, 0 ou 1 lorsque le premier opérande est respectivement inférieur, égal ou supérieur au deuxième opérande.
echo 1 <=> 2; // returns -1 echo 1 <=> 1; // returns 0 echo 2 <=> 1; // returns 1
Ce sont les nouvelles fonctionnalités les plus importantes ajoutées à PHP couvrant les versions 5.3 à 7.0. La liste des nouveautés supplémentaires, non listées dans cet article, peut être obtenue en parcourant la documentation de PHP sur la migration de version en version.
Ensuite, nous analysons comment tirer le meilleur parti de toutes ces nouvelles fonctionnalités et des tendances récentes du développement Web pour produire de meilleurs logiciels.
Recommandations des normes PHP
Les recommandations des normes PHP ont été créées par un groupe de développeurs PHP à partir de frameworks et de bibliothèques populaires, essayant d'établir des conventions afin que différents projets puissent être intégrés de manière plus transparente et que différentes équipes puissent mieux travailler les unes avec les autres. Les recommandations ne sont pas statiques : les recommandations existantes peuvent être obsolètes et de nouvelles créées pour les remplacer, et de nouvelles sont publiées en permanence.
Les recommandations actuelles sont les suivantes :
Grouper | Recommandation | La description |
---|---|---|
Styles de codage Le formatage standardisé réduit la friction cognitive lors de la lecture de code d'autres auteurs | PSR-1 | Norme de codage de base |
PSR-2 | Guide de style de codage | |
Chargement automatique Les chargeurs automatiques suppriment la complexité de l'inclusion de fichiers en mappant les espaces de noms aux chemins du système de fichiers | PSR-4 | Chargement automatique amélioré |
Interfaces Les interfaces simplifient le partage de code entre les projets en suivant les contrats attendus | PSR-3 | Interface de l'enregistreur |
PSR-6 | Interface de mise en cache | |
PSR-11 | Interface conteneur | |
PSR-13 | Liens hypermédias | |
PSR-16 | Cache simple | |
HTTP Normes et interfaces interopérables pour avoir une approche agnostique de la gestion des requêtes et des réponses HTTP, à la fois côté client et côté serveur | PSR-7 | Interfaces de messages HTTP |
PSR-15 | Gestionnaires HTTP | |
PSR-17 | Usines HTTP | |
PSR-18 | Client HTTP |
Penser et coder en composants
Les composants permettent d'utiliser les meilleures fonctionnalités d'un framework sans être enfermés dans le framework lui-même. Par exemple, Symfony a été publié sous la forme d'un ensemble de composants PHP réutilisables qui peuvent être installés indépendamment du framework Symfony ; Laravel, un autre framework PHP, utilise plusieurs composants Symfony et a publié son propre ensemble de composants réutilisables pouvant être utilisés par n'importe quel projet PHP.
Tous ces composants sont publiés dans Packagist, un référentiel de packages PHP publics, et peuvent être facilement ajoutés à n'importe quel projet PHP via Composer, un gestionnaire de dépendances extrêmement populaire pour PHP.
WordPress devrait faire partie d'un tel cycle de développement vertueux. Malheureusement, le noyau WordPress lui-même n'est pas construit à l'aide de composants (comme en témoigne l'absence quasi totale d'interfaces) et, de plus, il n'a même pas le fichier composer.json requis pour permettre l'installation de WordPress via Composer. En effet, la communauté WordPress n'a pas convenu si WordPress est une dépendance d'un site (auquel cas l'installer via Composer serait justifié) ou s'il s'agit du site lui-même (auquel cas Composer n'est peut-être pas le bon outil pour le travail) .
À mon avis, si nous voulons que WordPress reste pertinent pour les quinze prochaines années (au moins WordPress en tant que CMS backend), alors WordPress doit être reconnu comme une dépendance d'un site et rendu disponible pour l'installation via Composer . La raison est très simple : avec à peine une seule commande dans le terminal, Composer permet de déclarer et d'installer les dépendances d'un projet à partir des milliers de packages publiés dans Packagist, permettant de créer des applications PHP extrêmement puissantes en un rien de temps, et les développeurs adorent travailler de cette façon. Si WordPress ne s'adapte pas à ce modèle, il risque de perdre le soutien de la communauté de développement et de tomber dans l'oubli, d'autant que FTP est tombé en disgrâce après l'introduction des déploiements basés sur Git.
Je dirais que la sortie de Gutenberg démontre déjà que WordPress est une dépendance du site et non du site lui-même : Gutenberg traite WordPress comme un CMS sans tête et peut également fonctionner avec d'autres systèmes backend, comme l'illustre Drupal Gutenberg. Par conséquent, Gutenberg indique clairement que le CMS alimentant un site peut être échangeable, il doit donc être traité comme une dépendance. De plus, Gutenberg lui-même est destiné à être basé sur des composants JavaScript publiés via npm (comme expliqué par le committer principal Adam Silverstein), donc si le client WordPress est censé gérer ses packages JavaScript via le gestionnaire de packages npm, alors pourquoi ne pas étendre cette logique à le backend pour gérer les dépendances PHP via Composer ?
Maintenant la bonne nouvelle : il n'est pas nécessaire d'attendre que ce problème soit résolu puisqu'il est déjà possible de traiter WordPress comme une dépendance d'un site et de l'installer via Composer. John P. Bloch a mis en miroir le noyau de WordPress dans Git, ajouté un fichier composer.json et l'a publié dans Packagist, et Roots' Bedrock fournit un package pour installer WordPress avec une structure de dossiers personnalisée prenant en charge les outils de développement modernes et une sécurité renforcée. Et les thèmes et plugins sont également couverts ; tant qu'ils ont été répertoriés dans les répertoires de thèmes et de plugins WordPress, ils sont disponibles sous WordPress Packagist.
En conséquence, c'est une option judicieuse de créer du code WordPress ne pensant pas en termes de thèmes et de plugins, mais en termes de composants, les rendant disponibles via Packagist pour être utilisés par n'importe quel projet PHP, et en plus emballés et publiés en tant que thèmes et plugins pour l'utilisation spécifique de WordPress. Si le composant doit interagir avec les API WordPress, ces API peuvent être résumées derrière une interface qui, si nécessaire, peut également être implémentée pour d'autres CMS.
Ajout d'un moteur de modèle pour améliorer la couche de vue
Si nous suivons la recommandation de penser et de coder en composants et traitons WordPress comme une dépendance d'un site autre que le site lui-même, alors nos projets peuvent s'affranchir des limites imposées par WordPress et importer des idées et des outils tirés d'autres frameworks.
Le rendu du contenu HTML côté serveur en est un exemple, qui se fait via des modèles PHP simples. Cette couche de vue peut être améliorée grâce aux moteurs de templates Twig (par Symfony) et Blade (par Laravel), qui fournissent une syntaxe très concise et des fonctionnalités puissantes qui lui donnent un avantage sur les templates PHP simples. En particulier, les blocs dynamiques de Gutenberg peuvent facilement bénéficier de ces moteurs de modèles, car leur processus de rendu du code HTML du bloc côté serveur est découplé de l'architecture hiérarchique des modèles de WordPress.
Architecte de l'application à usage général
Le codage par rapport aux interfaces et la réflexion en termes de composants nous permettent de concevoir une application à usage général et de la personnaliser pour l'utilisation spécifique que nous devons fournir, au lieu de coder uniquement pour l'utilisation spécifique de chaque projet que nous avons. Même si cette approche est plus coûteuse à court terme (elle implique un travail supplémentaire), elle est payante à long terme lorsque des projets supplémentaires peuvent être livrés avec moins d'efforts en personnalisant simplement une application à usage général.
Pour que cette approche soit efficace, les considérations suivantes doivent être prises en compte :
Évitez les dépendances fixes (autant que possible)
jQuery et Bootstrap (ou Foundation, ou <–insérez votre bibliothèque préférée ici–> ) auraient pu être considérés comme des incontournables il y a quelques années, cependant, ils ont régulièrement perdu du terrain par rapport à vanilla JS et aux nouvelles fonctionnalités CSS natives. Ainsi, un projet à usage général codé il y a cinq ans qui dépendait de ces bibliothèques peut ne plus convenir de nos jours. Par conséquent, en règle générale, plus le nombre de dépendances fixes sur les bibliothèques tierces est faible, plus il s'avérera être à jour à long terme.
Amélioration progressive des fonctionnalités
WordPress est un système CMS complet qui inclut la gestion des utilisateurs. Par conséquent, la prise en charge de la gestion des utilisateurs est incluse dans la boîte. Cependant, tous les sites WordPress ne nécessitent pas de gestion des utilisateurs. Par conséquent, notre application doit en tenir compte et fonctionner de manière optimale sur chaque scénario : prendre en charge la gestion des utilisateurs chaque fois que nécessaire, mais ne pas charger les actifs correspondants chaque fois que ce n'est pas le cas. Cette approche peut également fonctionner progressivement : disons qu'un client a besoin d'implémenter un formulaire Contactez-nous mais n'a pas de budget, nous le codons donc à l'aide d'un plugin gratuit avec des fonctionnalités limitées, et un autre client a le budget pour acheter la licence à partir d'une offre de plugin commerciale meilleures fonctionnalités. Ensuite, nous pouvons coder notre fonctionnalité par défaut sur une fonctionnalité très basique et utiliser de plus en plus les fonctionnalités du plug-in le plus performant disponible dans le système.
Examen continu du code et de la documentation
En révisant périodiquement notre code précédemment écrit et sa documentation, nous pouvons valider s'il est soit à jour concernant les nouvelles conventions et technologies et, si ce n'est pas le cas, prendre des mesures pour le mettre à niveau avant que la dette technique ne devienne trop coûteuse à surmonter. et nous devons tout coder à nouveau à partir de zéro.
Lecture recommandée : Soyez vigilant : les fonctions PHP et WordPress qui peuvent rendre votre site non sécurisé
Essayez de minimiser les problèmes, mais soyez prêt quand ils se produisent
Aucun logiciel n'est jamais parfait à 100 % : les bogues sont toujours là, nous ne les avons tout simplement pas encore trouvés. En tant que tel, nous devons nous assurer que, une fois que les problèmes surviennent, ils sont faciles à résoudre.
Faites simple
Un logiciel complexe ne peut pas être maintenu à long terme : non seulement parce que les autres membres de l'équipe ne le comprennent peut-être pas, mais aussi parce que la personne qui l'a codé peut ne pas comprendre son propre code complexe dans quelques années. Donc produire un logiciel simple doit être une priorité, d'autant plus que seul un logiciel simple peut être correct et rapide.
Échouer au moment de la compilation est meilleur que lors de l'exécution
Si un morceau de code peut être validé par rapport aux erreurs au moment de la compilation ou de l'exécution, nous devons donner la priorité à la solution au moment de la compilation, afin que l'erreur puisse survenir et être traitée au stade du développement et avant que l'application n'atteigne la production. Par exemple, const
et define
sont utilisés pour définir des constantes, cependant, alors que const
est validé au moment de la compilation, define
est validé au moment de l'exécution. Ainsi, dans la mesure du possible, il est préférable d'utiliser const
plutôt que de define
.
Suite à cette recommandation, l'accrochage des fonctions WordPress contenues dans les classes peut être amélioré en passant la classe réelle en tant que paramètre au lieu d'une chaîne avec le nom de la classe. Dans l'exemple ci-dessous, si la classe Foo
est renommée, alors que le deuxième crochet produira une erreur de compilation, le premier crochet échouera à l'exécution, donc le deuxième crochet est meilleur :
class Foo { public static function bar() { } } add_action('init', ['Foo', 'bar']); // Not so good add_action('init', [Foo::class, 'bar']); // Much better
Pour la même raison que ci-dessus, nous devrions éviter d'utiliser des variables globales (telles que global $wpdb
) : celles-ci non seulement polluent le contexte global et ne sont pas faciles à suivre d'où elles proviennent, mais aussi, si elles sont renommées, l'erreur se produira être produit à l'exécution. Comme solution, nous pouvons utiliser un conteneur d'injection de dépendances pour obtenir une instance de l'objet requis.
Traiter les erreurs/exceptions
Nous pouvons créer une architecture d'objets Exception
, afin que l'application puisse réagir de manière appropriée en fonction de chaque problème particulier, soit pour s'en remettre chaque fois que possible, soit pour afficher un message d'erreur utile à l'utilisateur dans le cas contraire, et en général pour enregistrer l'erreur pour le administrateur pour résoudre le problème. Et protégez toujours vos utilisateurs de l'écran blanc de la mort : toutes les Error
et Exception
non détectées peuvent être interceptées via la fonction set_exception_handler
pour imprimer un message d'erreur non effrayant à l'écran.
Adoptez les outils de construction
Les outils de build permettent de gagner beaucoup de temps en automatisant des tâches très fastidieuses à exécuter manuellement. WordPress n'offre pas d'intégration avec un outil de construction spécifique, donc la tâche de les incorporer au projet incombera entièrement au développeur.
Il existe différents outils pour atteindre différents objectifs. Par exemple, il existe des outils de construction pour exécuter des tâches de compression et de redimensionnement d'images, de minification de fichiers JS et CSS et de copie de fichiers dans un répertoire pour produire une version, tels que Webpack, Grunt et Gulp ; d'autres outils aident à créer l'échafaudage d'un projet, ce qui est utile pour produire la structure de dossiers pour nos thèmes ou plugins, tels que Yeoman. En effet, avec autant d'outils autour, parcourir des articles comparant les différents outils disponibles aidera à trouver celui qui convient le mieux à nos besoins.
Dans certains cas, cependant, il n'y a pas d'outils de construction qui peuvent réaliser exactement ce dont notre projet a besoin, nous pouvons donc avoir besoin de coder notre propre outil de construction comme une extension du projet lui-même. Par exemple, j'ai fait cela pour générer le fichier service-worker.js afin d'ajouter la prise en charge des Service Workers dans WordPress.
Conclusion
En raison de son fort accent sur le maintien de la rétrocompatibilité, étendue même jusqu'à PHP 5.2.4, WordPress n'a pas été en mesure de bénéficier des dernières fonctionnalités ajoutées à PHP, et ce fait a fait de WordPress une plate-forme pas très excitante pour coder. pour parmi de nombreux développeurs.
Heureusement, ces jours sombres pourraient bientôt être révolus et WordPress pourrait redevenir une plate-forme brillante et passionnante pour laquelle coder : L'exigence de PHP 7.0+ à partir de décembre 2019 rendra disponible de nombreuses fonctionnalités PHP, permettant aux développeurs de produire des logiciels plus performants. Dans cet article, nous avons passé en revue les fonctionnalités PHP nouvellement disponibles les plus importantes et comment en tirer le meilleur parti.
La sortie récente de Gutenberg pourrait être un signe des bons moments à venir : même si Gutenberg lui-même n'a pas été pleinement accepté par la communauté, il démontre au moins une volonté d'intégrer les dernières technologies (telles que React et Webpack) dans le noyau . Cette tournure des événements me fait me demander : si le frontend peut faire peau neuve, pourquoi ne pas l'étendre au backend ? Une fois que WordPress nécessite au moins PHP 7.0, la mise à niveau vers des outils et des méthodologies modernes peut s'accélérer : bien que npm soit devenu le gestionnaire de packages JavaScript de choix, pourquoi ne pas faire de Composer le gestionnaire de dépendances PHP officiel ? Si les blocs sont la nouvelle unité pour construire des sites dans le frontend, pourquoi ne pas utiliser les composants PHP comme unité pour incorporer des fonctionnalités dans le backend ? Et enfin, si Gutenberg traite WordPress comme un CMS backend échangeable, pourquoi ne pas déjà reconnaître que WordPress est une dépendance du site et non le site lui-même ? Je vais laisser ces questions ouvertes pour que vous réfléchissiez et méditiez dessus.