Utiliser Pimple comme conteneur de service dans le développement WordPress
Dans mon dernier article pour Torque, j’ai parlé des avantages d’utiliser des conteneurs dans des plug – ins ou des applications WordPress. J’ai suivi le processus de conception des conteneurs à partir de zéro pour gérer trois classes Twitter: Feed, account et client. Cette semaine, j’étudierai des concepts très similaires, mais je parlerai plus de la construction de plug – ins autour de conteneurs. De plus, au lieu de faire défiler le nôtre, nous utiliserons Pimple, un excellent et assez standard paquet composer, comme conteneur. C’est là qu’on s’est arrêtés la dernière fois.
Catégorie de conteneur {
\/ * *
Objets contenant des traces
* *
Tableau des variables
* \/
$objet protégé;
\/ * *
Obtenir un client Twitter
* *
Retour à l’API Twitter
* \/
Gettwitter API (): fonctions publiques de l’API Twitter
{Y}
Si (! Isset ($this – > object [Method]) {
$this – > object [\ \ Method u] = new Twitter API ();
}
Renvoie $this – > objects [\ \ Method \ UU];
}
\/ * *
Obtenir un compte Twitter par nom d’utilisateur
* *
Chaîne de paramètres $nom d’utilisateur
* *
Retour au compte Twitter
* \/
Getwitteraccount (String $user name): Twitter account
{Y}
$arraykey = MD5 ($method. $user name);
Si (! Isset ($this – > objects [$arraykey]) {
$this – > objects [$arraykey] = Twitter accountfactory:: get ($user name);
}
Renvoie $this – > objects [$arraykey];
}
} c’est possible, mais l’ajout d’un nouvel élément au conteneur devient fastidieux. J’ai résisté à la tentation d’ajouter des abstractions pour rendre l’ajout de nouveaux éléments insignifiant. Non seulement j’essaie de démontrer une chose à la fois, mais je sais aussi que Pimple fournit tout ce dont nous avons besoin et est une norme familière à de nombreux développeurs PHP.
Si vous n’avez jamais utilisé Pimple auparavant, c’est un conteneur d’injection de dépendance très simple. Lorsque vous devez fournir un dépôt central flexible et testable pour une instance de classe partagée, il peut résoudre de nombreux problèmes
Vous devez être flexible pour combiner des instances individuelles avec des usines d’objets. En commençant par l’acné, nous n’avons qu’à nous inquiéter d’une seule catégorie: les contenants acné. Nous pouvons l’instancier ou l’étendre pour créer un conteneur. Pour une explication rapide, nous avons créé un conteneur et ajouté une seule instance \
Usine (fonction (c $)
Renvoie le nouveau client ();
}); Notez que cet objet implémente arrayaccess. C’est pourquoi nous pouvons utiliser la syntaxe Array pour accéder à ses éléments. Ainsi, nous pouvons maintenant accéder à notre instance client Twitter en utilisant: $client = $Container [‘twitter.client’]; Bien qu’artrayaccess soit propre, je préfère personnellement étendre Pimple et ajouter les méthodes get () et set (). La méthode Get () n’appelle que offset (), et set () n’appelle que offset (). Mais j’aime explicitement get () et set (), et je peux facilement les écraser dans les sous – classes sans avoir à réellement toucher l’implémentation arrayaccess fournie par Pimple.
Compensation (ID USD);
}
\/ * *
Définir l’objet dans le conteneur
* *
Parameter string $id
Mixed Parameter $value
* \/
Ensemble commun de fonctions (chaîne $ID, $value)
{Y}
Retourner $this – > offset ($ID, $value);
}
Avec cette nouvelle sous – classe Pimple, je peux utiliser arrayaccess ou une nouvelle méthode pour configurer et accéder aux éléments dans le conteneur. Dans l’article précédent, j’a i examiné la création d’une fonction pour inclure l’instance principale d’un conteneur, et c’est une meilleure façon d’atteindre le même objectif que d’utiliser un modèle d’instance unique dans une classe de conteneur. Voici comment nous pouvons utiliser la même méthode pour rendre le conteneur Pimple de notre plug – in globalement accessible sans forcer le mode Singleton à la classe conteneur:
<?php
/**
* Ottieni il contenitore del plugin
*
* @return \Pimple\Contenitore
*/
funzione pimpleExample() : \Pimple\Container
{
statico $contenitore;
if( ! $contenitore ){
$contenitore = new \Pimple\Container();
}
restituisce $contenitore;
} Ora possiamo usare questa funzione per ottenere l'istanza "principale" del contenitore, ma siamo comunque in grado di riutilizzare quel contenitore in un secondo momento. In effetti, è qualcosa che farò a breve: aggiungere un contenitore al contenitore. I contenitori agiscono per gestire lo stato degli oggetti in un'applicazione. Questo ci consente di iniziare a concettualizzare ogni parte della nostra app o plug-in come un servizio connesso alle altre parti tramite questo contenitore centrale.
Ad esempio, un'API molto importante in WordPress è l'API dei plug-in: gli hook AKA. Non è necessario utilizzare un intermediario per l'API Plugin. Possiamo semplicemente chiamare direttamente funzioni come add_filter(). Ma introducendo un intermediario possiamo trasformare l'API dei plugin in un servizio. Trattare questo modo fondamentale di comunicare con WordPress ha diversi vantaggi. L'utilizzo di un intermediario aggiunge un livello di disaccoppiamento da WordPress che rende il codice più testabile e aiuta nel refactoring futuro. Questo disaccoppiamento potrebbe tornare utile se alcuni hook devono essere reindirizzati, possibilmente a un'altra API, come l'API HTTP se diciamo che stai adottando un'architettura di microservizi più avanti nello sviluppo dell'applicazione. Inoltre, un buon intermediario dovrebbe aiutare nel monitoraggio dovrebbe aiutare a rimuovere i ganci, che è sempre un compito difficile.
Ci sono alcune buone astrazioni orientate agli oggetti per l'API dei plugin di WordPress là fuori. Uno che mi piace è netrivet/wp-event-emitter. Questa libreria funziona indipendentemente dal fatto che WordPress venga utilizzato o meno e dispone di maniglie per rimuovere bene gli hook. Usiamo l'aggiunta di un'istanza della classe NetRivet\WordPress\EventEmitter per iniziare a discutere su come strutturare il nostro plugin. Il primo passo nel nostro plugin è creare una classe per impostare lo stato del nostro plugin, iniziando con la registrazione dei servizi nel contenitore – Set (‘Ganci’, New eventemitter ();
}
}
Maintenant, nos fichiers pl
O _ add, $Priority, $acceptedargs);
}
\/ * *
Retour à eventemitterinterface
* \/
Gethookmanager (): eventemitterinterface
{Y}
Retourner pimpleexample () – > get (‘Hooks’);
}
} ainsi, nous pouvons refaire la façon d’ajouter un filtre, de sorte qu’il ressemble à ceci: Salut, Sean. ‘;
Renvoie $content;
}); Jusqu’à présent, nous avons créé une instance \
$this – > Main container = $main container;
}
\/ * *
Obtenez l’objet de compte du conteneur – si ce n’est pas le cas, envoyez l’annonce au conteneur.
* *
Chaîne de paramètres $nom d’utilisateur
* *
Retour au compte
* \/
Compte de fonction publique (chaîne $nom d’utilisateur): compte
{Y}
$key = ‘Account’. Sanitize _ Key ($user name);
Si ($this – > set container [$Key]) {
$this – > set container [$Key] = new Account ($user name, $Set [‘token], $Set [‘ tokensecret]);
}
Ra
Ouvrez $this – > set container [$Key]];
}
\/ * *
Obtenez l’objet d’alimentation du conteneur ADS au conteneur s’il n’existe pas.
* *
Chaîne de paramètres $nom d’utilisateur
* *
Retour à l’alimentation
* \/
Flux de fonctions publiques (chaîne $nom d’utilisateur): flux
{Y}
$key = ‘source’. Sanitize _ Key ($user name);
Si (! $this – > set container [$Key]) {
$this – > set container [$Key] = new source
$this – > Account ($user name),
$this – > Main Container [‘twitter.feed’]
);
}
Renvoie statique:: getContainer () [$Key]];
}
\/ * *
Obtenir un conteneur de compte
* *
Retour au conteneur
* \/
GetContainer () fonctions publiques: Container
{Y}
Retourner $this – > set container;
}
Notez que cette classe accepte son propre conteneur et le conteneur principal comme dépendances. Au début, je ne l’ai écrit que comme une classe statique, mais plus tard il était trop étroitement lié à l’instance principale du conteneur. De plus, je doute que je puisse le convertir en une autre classe abstraite comme un dépôt. Voici un registre de conteneur mis à jour pour créer cette instance dans le conteneur principal: Set (‘twitter.client’,
$conteneur – > usine (fonction ($c) {
Renvoie le nouveau client ();
})
);
Ajouter un gestionnaire de crochet
$Container – > Settings (‘Hooks’, New eventemitter ();
Ajouter une usine pour votre compte Twitter
$Container – > Settings (‘twitter.accounts’, New Factory (New container (), $container);
}
Cet article décrit comment utiliser Pimple comme conteneur dans un plug – in ou une application WordPress. J’ai montré la même chose dans mon dernier article, sans acné. Personnellement, je suis passé d’une mine de rouleaux utile pour le modèle d’apprentissage à l’utilisation de Pimple parce qu’il est meilleur et plus puissant que ma mise en oeuvre. J’ai réfléchi aux modèles d’architecture des microservices et aux modèles de fournisseurs de services et à la façon dont ils se ressemblent, mais à des échelles différentes. Première application liée
Pour former une application modulaire autour de l’application centrale. Ce dernier connecte différentes parties d’une seule application autour de la partie centrale de l’application. Ces méthodes sont très différentes de la façon dont nous utilisons habituellement WordPress. WordPress est simple car il n’est pas fortement encapsulé. La construction d’un plug – in ou d’une application autour d’un ou de plusieurs conteneurs de service aide à améliorer la réutilisabilité, la maniabilité et la testabilité du Code.