Widgets WordPress : refactorisation, partie 4
Nous avons implémenté un nombre important de modifications dans le WordPress Widget Boilerplate. Si vous n’avez pas suivi, je vous recommande de commencer au début de la série et de rattraper votre retard.
Si, toutefois, vous avez suivi et que vous utilisez également certains des outils de qualité du code qui examinent l’état du projet, vous remarquerez une poignée d’erreurs dans la console.
Normalement, c’est le point où je recommande de prêter attention à ce qu’il partage, puis de corriger tout ce qu’il rapporte, mais nous n’en sommes pas encore là.
Par exemple, certaines des erreurs que nos outils affichent actuellement sont basées sur le fait que nous avons des variables inutilisées. Bien sûr, c’est le cas, car nous n’avons pas commencé à créer un widget.
Mais il reste encore quelques classes concrètes que nous devons implémenter.
Le passe-partout du widget WordPress : refactorisation, partie 4
L’un des problèmes qui existent toujours dans le code tel qu’il est actuellement est que le constructeur du widget enregistre des fonctions et ce n’est pas une bonne chose.
Le but d’un constructeur est de définir les valeurs des propriétés de la classe, et non d’implémenter un type de logique. Ceci pour plusieurs raisons :
- il crée un fort couplage ou des dépendances entre les classes du projet chaque fois qu’une classe donnée est instanciée,
- il introduit une logique métier dans une fonction qui n’est pas destinée à contenir ladite fonctionnalité,
- il est difficile de tester une classe de manière isolée.
La façon de gérer cela est double :
- ajouter un registre que nous pouvons utiliser pour enregistrer des classes dans l’application (et les faire circuler avec le moins de dépendances possible, ce que j’expliquerai plus tard),
- créer des abonnés capables de gérer la logique métier sur une base spécifique au hook.
Au cours des trois prochains articles :
- nous allons envisager de créer un registre,
- comment on peut l’introduire dans le fichier bootstrap,
- puis envisagez de créer des abonnés pour chacune de nos fonctions (ce qui ne devrait pas être trop difficile compte tenu de ce que nous avons fait dans le post précédent et de ce que nous faisons dans ce post).
Créer le registre
Avant d’écrire le code du registre, il est important de noter son objectif principal. En termes simples, la classe est censée contenir une référence à toute classe qui est, ahem, enregistrée avec elle.
Cela se fait en passant une référence à un objet donné à une fonction et en la liant également à une clé afin que nous puissions facilement la récupérer plus tard.
Considérations initiales
Mais il y a certaines choses à considérer. Par exemple:
si un objet existe déjà dans le registre pour une clé donnée, alors nous devons lever une exception – si un utilisateur essaie de récupérer un objet dans le registre avec une clé donnée, alors il devrait lever une exception
Bien sûr, il ne doit pas nécessairement lever d’exceptions. Au lieu de cela, il peut également afficher des messages d’erreur, renvoyer des valeurs nulles ou vides, ou tout ce que vous choisissez.
Deuxièmement, le registre doit être en mesure de renvoyer une liste de tous les abonnés qui y sont contenus afin qu’ils puissent être enregistrés avec WordPress (c’est ce que nous allons voir dans le prochain article).
Pour ce faire, cependant, nous devons nous assurer qu’il prend en charge tous les abonnés et c’est là que la notion de AbstractSubscriber du post précédent entre en jeu. Autrement dit, tant qu’une classe est une classe enfant de cette classe, tout va bien.
Création du registre
Cela dit, planifions ce qui suit :
- Nous allons créer une classe Registry et la placer dans un espace de noms Utilities (et donc un répertoire) si elle n’existe pas déjà dans votre travail.
- Nous demanderons au registre de conserver une référence à tous ses objets dans un tableau associatif.
- Nous avons besoin de méthodes pour ajouter et obtenir un abonné individuel, puis une pour récupérer la liste des abonnés entiers.
Le stub de la classe ressemblera à ceci :
<?php
class Registry extends AbstractSubscriber
{
public function __construct()
{
}
public function add($id, $obj)
{
}
public function get($id)
{
}
public function getRegisteredSubscribers()
{
}
}
Ensuite, nous pouvons définir la propriété de base, un tableau, et l’initialiser dans le constructeur :
<?php
class Registry
{
private $registry;
public function __construct()
{
$this->registry = [];
}
// ...
}
Après cela, nous pouvons créer la méthode add. N’oubliez pas que dans mon implémentation, je choisis de lever une exception si une clé est déjà définie, mais vous n’avez pas à le faire.
<?php
public function add($id, $obj)
{
if (isset($this->registry[$id])) {
throw new Exception('An object already exists for this given key.');
}
$this->registry[$id] = $obj;
}
De même, la méthode get renverra une référence à l’instance d’un objet identifié avec cette clé. Si la clé n’est pas définie, elle lèvera une exception. S’il est défini, mais qu’aucun objet n’existe, nous renverrons null.
<?php
public function get($id)
{
if (!isset($this->registry[$id])) {
throw new Exception('No object exists for the specified key.');
}
return $this->registry[$id] ?? null;
}
Enfin, nous avons besoin d’une méthode pour renvoyer tous les abonnés enregistrés. Dans un prochain article, l’utilisation de cela deviendra beaucoup plus apparente, mais pour l’instant, notez que nous allons créer un tableau de n’importe quelle classe qui est une instance de la classe AbstractSubscriber , puis nous renverrons le tableau filtré.
<?php
public function getRegisteredSubscribers()
{
$subscribers = [];
foreach ($this->registry as $object) {
if ($object instanceof AbstractSubscriber) {
$subscribers[] = $object;
}
}
return array_filter($subscribers);
}
À ce stade, nous avons la classe complète (complète avec la documentation):
<?php
/*
* This file is part of the WordPress Widget Boilerplate
*
* (c) Tom McFarlin <tom@tommcfarlin.com>
*
* This source file is subject to the GPL license that is bundled
* with this source code in the file LICENSE.
*/
namespace WordPressWidgetBoilerplateUtilities;
use Exception;
use WordPressWidgetBoilerplateSubscriberAbstractSubscriber;
/**
* This class services as a simple container that can be used to pass objects
* around the plugin.
*
* To use this class you'd make a call to the registry by saying Registry->get(),
* then making a class to `register()` and `retrieve()` on an instance of the object.
*/
class Registry
{
/**
* @var array an array used to maintain the objects registered with the plugin
*/
private $registry;
/**
* Initializes the class by setting up the registry.
*/
public function __construct()
{
$this->registry = [];
}
/**
* Registers an object with the registry with the specified ID; however, will throw an
* exception if the ID is already referencing an object.
*
* @param string $id an ID by which the specified object will be referenced
* @param mixed $obj an instance of an object to store in the registry
*
* @throws Exception if an object already exists for the specified key
*/
public function add($id, $obj)
{
if (isset($this->registry[$id])) {
throw new Exception('An object already exists for this given key.');
}
$this->registry[$id] = $obj;
}
/**
* @param string $id the ID for the object that we wish to retrieve
*
* @throws Exception if no object exists for the specified key
*
* @return mixed a reference to the object or null
*/
public function get($id)
{
if (!isset($this->registry[$id])) {
throw new Exception('No object exists for the specified key.');
}
return $this->registry[$id] ?? null;
}
/**
* @return array all of the the Subscribers that should be registered with WordPress
*/
public function getRegisteredSubscribers()
{
$subscribers = [];
foreach ($this->registry as $object) {
if ($object instanceof AbstractSubscriber) {
$subscribers[] = $object;
}
}
return array_filter($subscribers);
}
}
Nous devons maintenant l’ajouter au bootstrap de notre plugin.
Avant le bootstrap, bien que
Comme mentionné précédemment dans le post, nous devons ajouter ceci au bootstrap du plugin. Pour ce faire, cependant, nous devons définir notre propre filtre afin de pouvoir facilement passer le registre autour du reste du plugin (le moment venu).
Avant de faire cela, cependant, il est important de s’assurer que vous maîtrisez bien le registre que nous venons de créer, qu’il s’intègre dans le plugin et que vous suivez avec la branche de développement que nous avons jusqu’à présent.