Chargement automatique orienté objet dans WordPress, 1ère partie

J'ai récemment terminé une série dans laquelle je couvrais les espaces de noms et le chargement automatique dans WordPress. Si vous ne connaissez pas l'un des termes ci-dessus, je vous recommande de consulter la série..

L'essentiel de ce que vous pouvez vous attendre à apprendre est le suivant:

Dans cette série, nous allons examiner exactement ce que sont les espaces de noms PHP, pourquoi ils sont bénéfiques et comment les utiliser. Ensuite, nous allons examiner comment utiliser des autochargeurs automatiques pour charger automatiquement les fichiers dont nous avons besoin sans avoir à les charger manuellement dans notre code..

Pendant que je travaillais sur la série, en particulier celle de l'autoloader, je ne pouvais m'empêcher de reconnaître un certain nombre d'odeurs de code introduites alors que je partageais le code avec vous..

Cela ne veut pas dire que l'autoloader est mauvais ou qu'il ne fonctionne pas. Si vous avez téléchargé le plugin, l’exécutez ou si vous avez suivi et écrit votre propre chargeur automatique, alors vous savez que Est-ce que en fait le travail.

Mais dans une série axée sur les espaces de noms, qui fait partie intégrante de la programmation orientée objet, je ne pouvais m'empêcher de me sentir mal à l'aise de laisser l'autochargeur dans son état final à la fin de la série..

Ne me lisez pas mal: je reste fidèle à la série, à ce qui était couvert et au résultat final de ce que nous avons produit. Mais d'un point de vue orienté objet, il reste encore beaucoup à faire. Donc, dans cette série de suivi, nous allons revisiter le concept d'autoloader du point de vue de la programmation orientée objet.

Plus précisément, nous allons parler du concept de:

  • interfaces
  • implémentation d'interface
  • le principe de responsabilité unique
  • et d'autres principes et idées qui sont au cœur de la programmation orientée objet

J'espère que d'ici à la fin de cette série, nous aurons non seulement transformé notre chargeur automatique en une version plus facile à gérer et à lire, mais qu'il adhèrera également à de plus grandes pratiques orientées objet..

Cela dit, commençons.

Commencer

Comme avec presque tous les articles que j'écris, j'aime essayer de faire deux choses:

  1. Définir une feuille de route indiquant où nous allons.
  2. Donnez-vous tout ce que vous devez savoir pour que votre machine soit opérationnelle.

Avant de nous lancer dans l'écriture de code, faisons-le maintenant. 

Notre feuille de route

Au cours des deux prochains articles, nous allons examiner certains concepts orientés objet qui vont nous permettre d’améliorer le plug-in que nous avons construit dans la série précédente.. 

Si vous ne possédez pas de copie de ce plugin, vous pouvez en télécharger une copie. Cependant, je partagerai des exemples de code complets, des commentaires et des explications tout au long de chaque tutoriel.. 

La série va supposer que vous savez rien sur tous les concepts que nous allons discuter afin que nous partions de la base. Tout ce dont vous avez besoin est d’avoir suffisamment de logiciels sur votre machine pour obtenir une copie de WordPress opérationnelle et un éditeur dans lequel vous pouvez éditer du code..

De quoi as-tu besoin

Pour commencer, vous aurez besoin des outils suivants:

  • Un environnement de développement local qui comprend au moins PHP 5.6.20, le serveur Web Apache et un serveur de base de données MySQL. MAMP 4 est parfait pour cela.
  • Un répertoire à partir duquel WordPress 4.6.1 est hébergé.
  • Un éditeur de texte ou un EDI de votre choix que vous maîtrisez bien pour écrire un plugin.
  • Une connaissance pratique de l'API du plugin WordPress.

Une fois que tout est en place (et je sais que cela semble beaucoup, mais que l'installation ne prend vraiment pas beaucoup de temps), vous devrez installer une copie du plug-in lié ci-dessus..

Une fois cela fait, nous sommes prêts à parler des interfaces et du principe de responsabilité unique.

Interfaces définies

En fonction de votre expérience dans le logiciel, lorsque vous entendez le mot "interface", vous pouvez finir par penser à ce que l'utilisateur voit réellement à l'écran. Vous savez: une interface utilisateur.

Mais lorsqu'il s'agit de conception orientée objet, ce n'est pas du tout ce dont nous parlons. Au lieu de cela, nous parlons d'une interface de classe. Et cela peut généralement être décrit comme la classe et les méthodes publiques qu’elle expose pour que les autres classes puissent communiquer avec elle..

Y a-t-il une définition plus formelle? Sûr. Wikipedia en offre un:

En informatique, une interface est une frontière partagée par laquelle deux composants distincts d’un système informatique échangent des informations..

Ce n'est pas si grave, en fait. C'est assez général pour s'appliquer à presque n'importe quel langage de programmation, et ce n'est pas alors technique que nous ne pouvons pas comprendre.

Là encore, nous travaillons avec PHP. Alors, que propose le manuel PHP sur le sujet??

Les interfaces d'objet vous permettent de créer un code qui spécifie les méthodes qu'une classe doit implémenter, sans avoir à définir comment ces méthodes sont gérées.

À mon avis, c'est une très bonne définition. C'est simple. Elle est agnostique (à ma connaissance) et fonctionne bien dans la plupart (sinon la totalité) des langages orientés objet. Le manuel poursuit même en disant:

Les interfaces sont définies de la même manière qu’une classe, mais avec le interface mot clé remplaçant le classe mot-clé et sans aucune des méthodes ayant leur contenu défini.
Toutes les méthodes déclarées dans une interface doivent être publiques; c'est la nature d'une interface.

Ce sont deux points que nous doit rappelez-vous si nous allons implémenter nos propres interfaces, surtout en ce qui concerne ce plugin. À savoir, nous devons nous rappeler les points suivants:

  1. Nous définissons une interface un peu comme nous faisons une classe, mais nous utilisons le interface mot-clé.
  2. Les méthodes définies dans une interface ont pour le public (par opposition à être protégé ou privé) car c’est ce qui garantit la fonctionnalité à laquelle les autres classes peuvent accéder.

Avant d'aller plus loin, à quoi pourrait ressembler une interface dans un projet WordPress? Voici un exemple d'un projet sur lequel j'ai travaillé:

Le code ci-dessus doit indiquer clairement à quoi il sert, en particulier compte tenu du commentaire placé au-dessus de l'interface..

Comme nous le savons tous, WordPress peut enregistrer et mettre en file d'attente deux types d’actifs: les feuilles de style et les fichiers JavaScript..

Étant donné que ces deux éléments sont des actifs, il serait logique de penser que lorsque nous créons des classes pour la gestion des feuilles de style ou du JavaScript, nous le généralisons en tant qu’interface d’actifs, à droite.?

De plus, nous savons que nous souhaitons initialiser le fichier à l’aide d’une méthode init afin que nous puissions relier la fonction de mise en file d'attente spécifiée à la fonction API WordPress appropriée. Alternativement, vous voudrez peut-être effectuer un autre travail et si c'est le cas, vous voudrez peut-être ajouter une autre signature de méthode à l'interface..

Quoi qu’il en soit, toute classe qui implémente cette interface doit fournir des fonctionnalités pour les méthodes suivantes. Alors à quoi ressemblerait une classe qui implémenterait cette interface?

Voici un exemple très simple d'une classe qui ajoute des feuilles de style à la zone d'administration de WordPress:

À présent Comment cela est instancié et appliqué via PHP dépasse le cadre de ce tutoriel. Nous verrons cela très souvent lorsque nous commencerons à refactoriser notre chargeur automatique.. 

Mais ce que j'essaie de montrer, c'est qu'une interface définit les méthodes publiques qu'une classe doit implémenter. Il ne définit pas l'implémentation, mais garantit qu'un certain ensemble de fonctions existera et sera accessible au public pour les classes tierces..

Le principe de responsabilité unique

L'un des problèmes que soulève le principe de la responsabilité unique est qu'il a souvent été mal interprété comme signifiant:

Une classe (ou une fonction ou une routine) doit faire une et une seule chose.

Mais c'est un peu égaré, n'est-ce pas? Je veux dire, même une boucle for simple fait plus d'une chose: elle initialise une valeur, la compare à des valeurs, puis itère la valeur lorsque le corps de la boucle est terminé.

Au lieu de cela, le principe énonce ce qui suit:

Une classe ne devrait avoir qu'une seule raison de changer.

Étant donné que nombre d'entre nous, développeurs, exploitons Google pour nous aider dans notre travail quotidien, je pense qu'il est important de comprendre la source de cette idée. C’est-à-dire que cela vient de l’oncle Bob Martin, comme il est surnommé par hasard, ou de Robert Martin, qui est l'auteur de nombreux livres de programmation de premier plan.

L'idée d'une classe n'ayant qu'une seule raison de changer comporte de nombreuses implications, n'est-ce pas? Voici un exemple qui vient à l’esprit de notre chargeur automatique tel qu’il est aujourd’hui.

Passons en revue le code (et je sais que ce n'est pas une classe, c'est une fonction, mais le principe est applicable):

 0; $ i--) // Lit le composant actuel de la partie du fichier. $ current = strtolower ($ file_parts [$ i]); $ current = str_ireplace ('_', '-', $ current); // Si nous en sommes à la première entrée, alors nous sommes au nom du fichier. if (count ($ file_parts) - 1 === $ i) / * Si 'interface' est contenu dans les parties du nom du fichier, alors * définissons le $ nom_fichier différemment pour qu'il soit correctement chargé. * Sinon, définissez simplement $ nom_fichier égal à celui de la structure de la classe * nom_fichier. * / if (strpos (strtolower ($ file_parts [count ($ fichiers_fichiers) - 1]), 'interface')) ) Extrait le nom de l'interface de son nom qualifié. $ nom_interface = exploser ('_', $ pièces_fichiers [count ($ pièces_fichiers) - 1]); $ nom_interface = $ nom_interface [0]; $ nom_fichier = "interface- $ nom_interface.php";  else $ nom_fichier = "class- $ current.php";  else $ namespace = '/'. $ actuel. $ namespace;  // Créez maintenant un chemin d'accès au fichier en utilisant un mappage vers l'emplacement du fichier. $ filepath = trailingslashit (dirname (dirname (__FILE__)). $ namespace); $ filepath. = $ nom_fichier; // Si le fichier existe dans le chemin spécifié, incluez-le. if (file_exists ($ filepath)) include_once ($ filepath);  else wp_die (esc_html ("Le fichier qui tente d'être chargé à $ filepath n'existe pas."));  

Il y a beaucoup de choses qui se passe dans cette fonction. En le regardant d'un niveau élevé, on peut voir qu'il fait ce qui suit:

  • Il détermine si PHP essaie d'invoquer le code dans cette fonction..
  • La fonction détermine si nous chargeons une interface ou une classe.
  • L'autoloader tente ensuite d'inclure le fichier ou génère une erreur..

Si une classe est supposée avoir seulement une raison de changer, il y a trois raisons ci-dessus (et c'est juste à un niveau élevé) pour lesquelles cette fonction unique pourrait changer. En outre, le code pourrait être plus clair, ainsi que.

Je ne suis pas du genre à craindre les commentaires de code, mais il y a beaucoup d'explications dans le code ci-dessus. Et c'est bien quand vous commencez tout juste à écrire un autochargeur, mais si vous vous dirigez vers un territoire plus avancé comme celui que nous sommes, cela ne résistera pas à des architectures plus rigoureuses..

Réunir les deux

C’est là que les interfaces et le principe de responsabilité unique peuvent être associés.

Tout comme une interface fournit un ensemble de signatures de fonction (ou un contrat) pour ce que ses implémenteurs fourniront, elle peut garantir que toute classe implémentant cette interface respecte scrupuleusement ce qu'elle définit..

Mais cela soulève une question intéressante: devrions-nous avoir plusieurs interfaces? Et la réponse est que cela dépend de la nature de la solution que vous essayez de créer.. 

Dans notre cas, je pense que cela a du sens. 

Après tout, nous cherchons à examiner le nom d’une classe entrante et à déterminer s’il s’agit d’une interface ou d’une classe, ou si elle mérite de générer une erreur. De plus, nous cherchons à nous assurer que le fichier approprié est inclus avec le reste du système..

Mais cela va au-delà du sujet de ce tutoriel et nous devrons approfondir ce sujet au moment d’écrire plus de code..

Conclusion

À ce stade, nous avons abordé les concepts nécessaires pour pouvoir commencer à refactoriser notre chargeur automatique. En d'autres termes, nous allons introduire une interface en nous assurant que notre code y adhère, puis nous nous assurerons que notre classe (ou classes) et leurs méthodes respectives adhèrent au principe de responsabilité unique..

De plus, nous allons nous assurer qu'il continue à bien fonctionner dans le contexte du plugin, qu'il est correctement documenté et qu'il respecte les normes de codage WordPress..

En attendant, si vous souhaitez en savoir plus sur la programmation orientée objet dans le contexte de WordPress, vous pouvez retrouver tous mes tutoriels précédents sur ma page de profil. N'hésitez pas à me suivre sur mon blog ou à me suivre sur Twitter où je parle souvent des deux.

Comme toujours, si vous recherchez d'autres utilitaires pour vous aider à développer votre ensemble croissant d'outils pour WordPress ou, par exemple, du code pour étudier et mieux connaître WordPress, n'oubliez pas de voir ce que nous avons disponible dans Envato Market..

Cela dit, le prochain tutoriel de la série sera beaucoup plus pratique. Autrement dit, nous allons écrire du code, refactoriser le code existant et appliquer tout ce que nous avons appris dans ce tutoriel. D'ici là, n'hésitez pas à laisser des commentaires dans les commentaires.

Ressources

  • Espace de noms et plugin Autoloader
  • Espaces de noms
  • Chargement automatique
  • Des interfaces
  • L'API du plugin WordPress
  • MAMP 4
  • Principe de responsabilité unique