Enregistrement de crochets WordPress à l’aide d’une autre classe
Dans le post d’hier, j’ai parlé d’un constructeur de plugins WordPress et de la raison pour laquelle les crochets ne devraient pas être dans le constructeur.
Bien que j’ai mentionné un certain nombre de façons de gérer l’enregistrement des hooks, je n’ai pas pris la peine d’entrer dans les détails de chacune de ces stratégies. En ce qui me concerne, ils méritent leur propre article afin de fournir le plus de détails possible sur la façon de configurer quelque chose.
Par exemple, l’une des méthodes que j’ai partagées indiquait :
- Il est possible de créer une classe qui maintient un registre d’objets et les crochets avec WordPress.
En d’autres termes, il s’agit d’enregistrer les crochets WordPress en utilisant une approche orientée objet pour réduire le couplage et augmenter la cohésion entre les composants du plugin.
Mais qu’est-ce que cela signifie même? Quels sont les avantages qu’il apporte, comment est-il configuré et comment est-il utilisé ?
Enregistrement de crochets WordPress
Si vous lisez ceci, vous connaissez probablement le système de hook WordPress, l’ordre dans lequel ils sont déclenchés et comment une fonction ou une classe peut enregistrer ses fonctions auprès de WordPress afin qu’elles puissent effectuer tout le travail dont elles ont besoin.
Et nous voyons souvent des classes le faire par elles-mêmes. Selon le projet, je le fais moi-même. Pour ceux qui ne connaissent pas, cela ressemble généralement à ceci :
<?php
add_action( 'plugins_loaded', 'acme_start' );
/**
* Start the machine.
* https://www.youtube.com/watch?v=ysoMOefPyRs
*/
function acme_start() {
$plugin = new AcmeColumn();
}
Mais tout cela peut être décomposé en classes plus cohérentes pour finalement leur donner encore moins de responsabilités (une bonne chose) et pour diminuer le couplage entre une classe ou un ensemble de classes avec WordPress.
Un exemple de design que je vais détailler dans cet article.
La nature contre-intuitive de cela, cependant, est que cela nécessitera au moins une autre classe. Mais voici comment cela fonctionne.
Le configurer
Pour les besoins de cet exemple, nous allons simplement utiliser une classe simple qui va enregistrer un certain type d’action avec WordPress. L’idée de l’architecture fonctionne quelque chose comme ceci:
- Il y a la classe principale qui a la fonction que nous voulons accrocher à WordPress.
- Il y a une classe chargée d’orchestrer l’accrochage de la fonction de la classe à WordPress.
Assez facile, non? Mais voici le hic: la classe responsable de l’enregistrement des fonctions d’une classe donnée avec WordPress est le point qui nécessite une décision de conception.
Tout d’abord, appelons la classe HookRegistry afin que nous puissions nous y référer correctement. Ensuite, appelons la classe avec les fonctions que nous voulons accrocher AcmeColumn simplement pour représenter une classe qui ajoute une nouvelle colonne au tableau de bord Page dans la zone d’administration de WordPress.
Avec cela en place, la décision de conception se résume à ceci :
- Le HookRegistery devrait- il connaître AcmeColumn ?
- AcmeColumn devrait -il connaître le HookRegistry?
Je sais qu’il existe d’autres façons d’organiser cela et il existe également des stratégies pour gérer cela (comme l’ inversion de contrôle) et ce sont des sujets qui valent la peine d’être explorés, mais pour garder cette idée initiale aussi simple que possible, je vais la déposer pour un futur poste.
Utilisation de la classe
Compte tenu des options ci-dessus, nous transmettrons une instance de AcmeColumn dans HookRegistry lorsque les classes seront instanciées lors du processus de démarrage initial du plugin WordPress. Cela peut ressembler à ceci :
<?php
add_action( 'plugins_loaded', 'acme_start' );
/**
* Start the machine.
* https://www.youtube.com/watch?v=ysoMOefPyRs
*/
function acme_start() {
$registry = new HookRegistry();
$acme_column = new AcmeColumn( $registry );
$acme_column->start();
}
Ensuite, chaque fois qu’il est temps de demander à AcmeColumn d’enregistrer sa fonction auprès de WordPress, nous appellerons HookRegistry et lui demanderons de le faire.
Tout d’abord, AcmeColumn :
<?php
class AcmeColumn {
private $registry;
public function __construct( $registry) {
$this->registry = $registry;
}
public function start() {
$registry->add_hook( 'filter', 'manage_edit-page_columns', $this, 'add_page_column' );
}
public function add_page_column( $page_columns) {
$page_columns['template'] = 'Acme Column';
return $page_columns;
}
}
Puis le HookRegistry :
<?php
class HookRegistry {
public add_hook( $type, $name, $object, $method) {
$type = strtolower( $type );
if ('filter' !== $type || 'action' !== $type) {
return new WP_Error( '1', 'No proper hook type defined.' );
}
}
private function add_filter( $name, $object, $method) {
add_filter( $name, array( $object, $method) );
}
private function add_action( $name, $object, $method) {
add_action( $name, array( $object, $method) );
}
}
En option, nous pouvons également maintenir une liste des différentes classes et crochets qui ont été enregistrés. Cela peut être utile ou non en fonction de votre mise en œuvre, donc je partage uniquement comme "voici quelque chose que vous voudrez peut-être faire".
Et cela pourrait ressembler à ceci (en utilisant un simple tableau associatif):
<?php
class HookRegistry {
private $registry;
public function __construct() {
$this->registery = array();
}
public add_hook( $id, $type, $name, $object, $method) {
$type = strtolower( $type );
if ('filter' !== $type || 'action' !== $type) {
return new WP_Error( '1', 'No proper hook type defined.' );
}
if ('filter' === $type) {
$this->add_filter( $name, $object, $method );
} else {
$this->add_action( $name, $object, $method );
}
$hook_info = array(
$type,
$name,
$object,
$method,
);
$this->registry[ $id ] = $hook_info;
}
private function add_filter( $name, $object, $method) {
add_filter( $name, array( $object, $method) );
}
private function add_action( $name, $object, $method) {
add_action( $name, array( $object, $method) );
}
}
Notez que dans la classe ci-dessus, elle accepte désormais un $id comme paramètre. Il existe plusieurs façons d’identifier les informations qui entrent dans un registre, la plus simple étant de créer l’ID vous-même.
Cependant, si vous vouliez utiliser quelque chose comme le nom du crochet ou le nom de la classe, cela fonctionnerait aussi. Notez simplement que, puisqu’il s’agit d’un tableau associatif, il ne peut conserver qu’une seule valeur par clé, vous pouvez donc finir par supprimer les données précédentes si vous ne faites pas attention.
Quoi qu’il en soit, c’est quelque chose que je considère comme facultatif, mais s’il est implémenté, il est important de s’assurer que vous disposez des fonctions appropriées pour récupérer une instance de l’objet par une clé.
Un parmi beaucoup
Comme pour tout ce qui concerne ce type de travail, il est possible de le réorganiser ou de le réorienter d’une manière qui fonctionne différemment ou qui répond à vos besoins. Le but n’est pas de montrer le modèle définitif pour savoir comment faire quelque chose, mais une façon de l’aborder et de l’adapter (un peu comme n’importe quel modèle de conception).
De plus, cela vise à s’assurer que nos classes conservent les responsabilités pour lesquelles elles ont été créées tout en leur permettant de s’enregistrer auprès de WordPress au besoin. Cette fois, cependant, la classe n’a pas à le faire elle-même.
Au lieu de cela, il passe la responsabilité à une classe qui a la seule responsabilité d’enregistrer lesdits crochets. Ainsi, bien qu’il introduit plus de classes, il augmente la cohésion et diminue le couplage.
Cela offre des avantages en matière de maintenance, de test et de conception globale.