Dans mon dernier article pour Torque, j’ai parlé des avantages d’utiliser des conteneurs dans des plug ins ou des applications WordPress. Jrsquoai suivi le processus de conception des conteneurs à partir de zéro pour gérer trois classes Twitter: Feed, account et client. Cette semaine, jrsquoé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. Crsquoest là qursquoon srsquoest 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 à lrsquoAPI Twitter
*
Gettwitter API (): fonctions publiques de lrsquoAPI Twitter
{Y}
(! Isset ($this gt object [Method]) {
$this gt object [ Method u] = new Twitter API ()
}
Renvoie $this gt objects [ Method UU]
}
* *
Obtenir un compte Twitter par nom drsquoutilisateur
* *
Chaîne de paramètres $nom drsquoutilisateur
* *
Retour au compte Twitter
*
Getwitteraccount (String $user name): Twitter account
{Y}
$arraykey = MD5 ($method. $user name)
(! Isset ($this gt objects [$arraykey]) {
$this gt objects [$arraykey] = Twitter accountfactory:: get ($user name)
}
Renvoie $this gt objects [$arraykey]
}
} crsquoest possible, mais lrsquoajout drsquoun nouvel élément au conteneur devient fastidieux. Jrsquoai résisté à la tentation drsquoajouter des abstractions pour rendre lrsquoajout de nouveaux éléments insignifiant. Non seulement jrsquoessaie 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.
nrsquoavez jamais utilisé Pimple auparavant, crsquoest un conteneur drsquoinjection de dépendance très simple. Lorsque 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 drsquoobjets. En commençant par lrsquoacné, nous nrsquoavons qursquoà nous inquiéter drsquoune seule catégorie: les contenants acné. Nous pouvons lrsquoinstancier ou lrsquoé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. Crsquoest 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 [lsquotwitter.clientrsquo] Bien qursquoartrayaccess soit propre, je préfère personnellement étendre Pimple et ajouter les méthodes get () et set (). La méthode Get () nrsquoappelle que offset (), et set () nrsquoappelle que offset (). Mais jrsquoaime explicitement get () et set (), et je peux facilement les écraser dans les sous classes sans avoir à réellement toucher lrsquoimplémentation arrayaccess fournie par Pimple.
Compensation (ID USD)
}
* *
Définir lrsquoobjet dans le conteneur
* *
Parameter string $id
Mixed Parameter $value
*
Ensemble commun de fonctions (chaîne $ID, $value)
{Y}
Retourner $this gt 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 lrsquoarticle précédent, jrsquoa i examiné la création drsquoune fonction pour inclure lrsquoinstance principale drsquoun conteneur, et crsquoest une meilleure façon drsquoatteindre le même objectif que drsquoutiliser un modèle drsquoinstance 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 ngleton à la classe conteneur:
lt?php
**
* Ottieni il contenitore del plugin
*
* @return PimpleContenitore
*
funzione pimpleExample() : PimpleContainer
{
statico $contenitore
if( ! $contenitore ){
$contenitore = new PimpleContainer()
}
restituisce $contenitore
} Ora possiamo usare questa funzione per ottenere l039istanza quotprincipalequot 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 un039applicazione. 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, un039API molto importante in WordPress è l039API dei plug-in: gli hook AKA. Non è necessario utilizzare un intermediario per l039API Plugin. Possiamo semplicemente chiamare direttamente funzioni come add_filter(). Ma introducendo un intermediario possiamo trasformare l039API dei plugin in un servizio. Trattare questo modo fondamentale di comunicare con WordPress ha diversi vantaggi. L039utilizzo 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 un039altra API, come l039API HTTP se diciamo che stai adottando un039architettura di microservizi più avanti nello sviluppo dell039applicazione. 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 l039API dei plugin di WordPress là fuori. Uno che mi piace è netrivetwp-event-emitter. Questa libreria funziona indipendentemente dal fatto che WordPress venga utilizzato o meno e dispone di maniglie per rimuovere bene gli hook. Usiamo l039aggiunta di un039istanza della classe NetRivetWordPressEventEmitter 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 (lsquoGancirsquo, New eventemitter ()
}
}
Maintenant, nos fichiers pl
O _ add, $Priority, $acceptedargs)
}
* *
Retour à eventemitterinterface
*
Gethookmanager (): eventemitterinterface
{Y}
Retourner pimpleexample () gt get (lsquoHooksrsquo)
}
} ainsi, nous pouvons refaire la façon drsquoajouter un filtre, de sorte qursquoil ressemble à ceci: Salut, Sean. lsquo
Renvoie $content
}) Jusqursquoà présent, nous avons créé une instance
$this gt Main container = $main container
}
* *
Obtenez lrsquoobjet de compte du conteneur si ce nrsquoest pas le cas, envoyez lrsquoannonce au conteneur.
* *
Chaîne de paramètres $nom drsquoutilisateur
* *
Retour au compte
*
Compte de fonction publique (chaîne $nom drsquoutilisateur): compte
{Y}
$key = lsquoAccountrsquo. Sanitize _ Key ($user name)
($this gt set container [$Key]) {
$this gt set container [$Key] = new Account ($user name, $Set [lsquotoken], $Set [lsquo tokensecret])
}
Ra
Ouvrez $this gt set container [$Key]]
}
* *
Obtenez lrsquoobjet drsquoalimentation du conteneur ADS au conteneur srsquoil nrsquoexiste pas.
* *
Chaîne de paramètres $nom drsquoutilisateur
* *
Retour à lrsquoalimentation
*
Flux de fonctions publiques (chaîne $nom drsquoutilisateur): flux
{Y}
$key = lsquosourcersquo. Sanitize _ Key ($user name)
(! $this gt set container [$Key]) {
$this gt set container [$Key] = new source
$this gt Account ($user name),
$this gt Main Container [lsquotwitter.feedrsquo]
)
}
Renvoie statique:: getContainer () [$Key]]
}
* *
Obtenir un conteneur de compte
* *
Retour au conteneur
*
GetContainer () fonctions publiques: Container
{Y}
Retourner $this gt set container
}
Notez que cette classe accepte son propre conteneur et le conteneur principal comme dépendances. Au début, je ne lrsquoai écrit que comme une classe statique, mais plus tard il était trop étroitement lié à lrsquoinstance 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 (lsquotwitter.clientrsquo,
$conteneur gt usine (fonction ($c) {
Renvoie le nouveau client ()
})
)
Ajouter un gestionnaire de crochet
$Container gt Settings (lsquoHooksrsquo, New eventemitter ()
Ajouter une usine pour votre compte Twitter
$Container gt Settings (lsquotwitter.accountsrsquo, New Factory (New container (), $container)
}
Cet article décrit comment utiliser Pimple comme conteneur dans un plug in ou une application WordPress. Jrsquoai montré la même chose dans mon dernier article, sans acné. Personnellement, je suis passé drsquoune mine de rouleaux utile pour le modèle drsquoapprentissage à lrsquoutilisation de Pimple parce qursquoil est meilleur et plus puissant que ma mise en oeuvre. Jrsquoai réfléchi aux modèles drsquoarchitecture 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 lrsquoapplication centrale. Ce dernier connecte différentes parties drsquoune seule application autour de la partie centrale de lrsquoapplication. 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 drsquoun plug in ou drsquoune application autour drsquoun ou de plusieurs conteneurs de service aide à améliorer la réutilisabilité, la maniabilité et la testabilité du Code.
Utiliser Pimple comme conteneur de service dans le développement WordPress