Les deux choses que j’ai écrit le plus sur Torque sont le PHP orienté objet et l’api WordPress rest. Dans je vais les rassembler pour montrer comment créer une collection de chemins API de repos personnalisés en appliquant les principes de PHP orienté objet. Lrsquoun des avantages de lrsquohéritage en PHP orienté objet est qursquoil nous permet de partager le Code entre les classes. Il y a de nombreuses façons drsquoéviter de nous répéter dans le Code. Lrsquohéritage en est un et ne devrait être utilisé que lorsque deux classes ou plus ont des objectifs similaires. avez une classe qui crée une page drsquoadministration et une classe qui gère la recherche, devrez peut être partager le Code, mais il nrsquoest pas logique qursquoils étendent la même classe de base parce qursquoils font des choses complètement différentes. Drsquoautre part, si avez une classe qui crée un paramètre API rest pour un produit et une autre qui génère un paramètre API rest pour les documents sur ces produits, il est logique que les deux classes partagent une classe de base commune.
Dans apprendrez comment concevoir un système pour créer des paramètres d’api WordPress rest, en tirant parti de l’héritage de classe et en tirant parti de la visibilité et des autres principes dont j’ai discuté précédemment. nrsquoêtes pas familier avec les paramètres personnalisés de lrsquoAPI rest, consultez le Guide final de lrsquoAPI rest avant de procéder. Je recommande également de voir comment les chemins de type post sont construits dans le plug in rest API, qui tire pleinement parti de lrsquohéritage de classe pour créer des chemins pour chaque type de post. Pour concevoir un système drsquoarchitecture pour un exemple complet drsquoun système API rest, nous avons trois questions générales:
Par exemple, lorsque je crée une route, je crée une classe abstraite pour la route CRUD. Je vais également créer une interface plus générique que ces chemins implémenteront. La raison pour laquelle avez une interface est que si ajoutez un chemin
Ce modèle ne correspond pas très bien et ne devriez pas les forcer à y adhérer. En même temps, la classe du système de démarrage doit pouvoir srsquoattendre à la structure de classe spécifique de lrsquoobjet de routage qursquoelle gère. Ensuite, il est recommandé que la méthode de démarrage du système dans la classe nrsquoaccepte que la classe qui implémente lrsquointerface. Il lui permet drsquoaccepter des classes qui étendent les classes de base CRUD, mais si nous ajoutons des routes non CRUD, nous perdons beaucoup de flexibilité et nous devons écraser le système.
La troisième tâche consiste à créer des réponses. Par exemple, je ne créerai qursquoune classe de réponse générale réussie et une classe drsquoerreur. Ils étendront la réponse WP _ rest et lrsquoerreur WP respectivement et ne feront rien drsquoautre. Cependant, comme tous les chemins renvoient ces objets, nrsquoavez pas besoin de Refactoring plus tard si avez besoin de propriétés communes dans la réponse, pouvez simplement ajouter des méthodes à ces classes. Dans cet exemple, jrsquoutiliserai la structure du Répertoire et lrsquoespace de noms du PSR 4. Lrsquoavantage du PSR 4 est qursquoil rend la structure du répertoire utile pour définir la fonctionnalité du Code. En général, jrsquoaide simplement à imaginer ce dont jrsquoa i besoin pour démarrer un projet en arrangeant un catalogue. Voici la structure de ce générateur drsquoapi rest:
En commençant par les interfaces contractuelles, créez les contrats que les classes qui les implémentent doivent suivre. Dans ce cas, nous nrsquoutiliserons qursquoune seule interface, ce qui signifie que chaque classe qui lrsquoimplémente doit avoir une méthode appelée « ajouter _ routes » qui accepte un paramètre appelé espace de noms. Par conséquent, nous pouvons être sûrs que tous les objets qui lrsquoimplémentent ont cette méthode et peuvent lrsquoutiliser de façon prévisible. La façon dont ils gèrent les chemins ajoutés nrsquoa pas drsquoimportance. Notre cours de base CRUD définira un modèle. Classe orientale
Ou ils peuvent écraser la méthode. Drsquoautres classes peuvent implémenter cette interface à condition qursquoelles satisfassent aux conditions du Protocole définies par cette interface.
Crsquoest notre interface, très simple: le chemin de lrsquointerface {
Fonction publique add _ routes ($namespace)
} créer une classe abstraite nous créons maintenant une classe abstraite appelée CRUD qui implémente cette interface. Apparemment, il doit avoir une méthode appelée
Voici à quoi ressemble cette méthode:
Hériter du document
*
Fonction publique add _ routes ($namespace) {
$base = $this gt route _ base ()
Register _ rest route ($namespace, lsquorsquo. $base
[2]
« méthode» = gt wp _ rest Server:: lisible,
« callback» = gt [$this, lsquoget _ item],
« permissions _ callback» = gt [$this, lsquoget item permissions check],
« par» = gt
« par défaut» = gt 1,
« sanitize _ callback» = gt « absent»,
],
« limite» = gt
« par défaut» = gt 10,
« sanitize _ callback» = gt « absent»,
[1]
],
],
[2]
« méthode» = gt wp _ rest Server:: creatable,
« callback» = gt [$this, lsquocreate _ item],
« permissions _ callback» = gt [$this, lsquocreate items permissions checks],
],
[1]
)
Register _ rest route ($namespace,
[2]
« méthode» = gt wp _ rest Server:: lisible,
« callback» = gt [$this, lsquoget _ item],
« permission _ callback» = gt [$this, lsquoget item permissions check],
« contexte» = gt
« par défaut» = gt « vue»,
[1]
],
],
[2]
« méthode» = gt wp _ rest Server:: modifiable
Les chaussures bien aimées élargissent la classe et cette méthode renvoie les chaussures. Vous avez peut être remarqué que ceci est utilisé dans la méthode add _ routes pour former lrsquoURL du paramètre.
La troisième méthode de ce groupe est appelée
jrsquoécris cette classe uniquement pour lrsquoutiliser en PHP 7, je mrsquoassure que chacune de ces trois méthodes a un type de retour déclaré pour mrsquoassurer qursquoelles renvoient toujours le bon type de données. Ainsi, si les écrasez dans une sous classe, ils retourneront certainement le bon type. Lrsquoensemble suivant de méthodes est la méthode de réponse finale. Chaque méthode renvoie une méthode non _ yet response. Je lrsquoai expliqué. Un autre avantage de cette approche est que dans une sous classe de cette classe, les documents en ligne peuvent utiliser @ inheritdoc au lieu de copier le même document en ligne nrsquoimporte où. Une autre chose à garder à lrsquoesprit à propos de ces méthodes est qursquoelles sont publiques. Ils doivent lrsquoêtre parce qursquoils sont appelés par la classe WP _ rest Server. Tout autre paramètre de visibilité génère une erreur. Mais nous ne voulons pas utiliser ces méthodes dans un contexte autre que la réponse à une demande drsquoapi rest. Crsquoest pourquoi jrsquoai entré les paramètres qui leur suggéraient drsquoaccepter comme objet de classe WP _ rest request. Cela signifie que les classes peuvent les utiliser
La classe de réponse aux erreurs nrsquoa même pas de corps. Cependant, en commençant par ces classes et en les utilisant au lieu de la classe principale étendue, au fur et à mesure que le système évolue, il est facile drsquoajouter des méthodes utilitaires à ces classes, ou drsquoécraser les méthodes de la classe principale et de les appliquer à toutes les réponses de cette API. Crsquoest ma classe de réponse principale: espace de noms Josh API Responses
Extension de la réponse de classe
Fonction commune construction ($Data, $Status, Array $Header) {
Parent: u Construct ($Data, $Status, $headers)
(NULL ($Data) {
$this gt SET _ Status (404)
}
}
Comme pouvez le voir, crsquoest simple. Ce nrsquoest qursquoun point de départ. Ma seule décision est de vérifier si les données retournées sont vides, auquel cas réinitialiser le Code drsquoétat à 404. Crsquoest une décision imprudente, mais drsquoaprès mon expérience, elle simplifie les choses. Comme je lrsquoai dit, ma réponse aux erreurs nrsquoétend que les erreurs WP _ et ne fait rien drsquoautre. Mais crsquoest un pari équitable parce que jrsquoutilise ce système et je veux ajouter une fonctionnalité pour toutes les erreurs, donc je veux commencer par ma classe drsquoerreurs drsquoapi rest. Espace de noms Josh API error
Extension drsquoerreur de classe
} maintenant, pour montrer comment cela fonctionne, nous avons créé une classe qui étend
Mes données seront supprimées plus tard des messages personnalisés et des champs. Je crois fermement qursquoil est essentiel de créer lrsquoabstraction de la base de données dès le début, tout comme Pippin Williamson lrsquoa fait ici. Comme je ne voulais pas lier lrsquoAPI rest entière à la requête WP _ U, je nrsquoai pas mis les méthodes prepare items for Response et prepare items for Response dans la classe de base. Le plug in principal de lrsquoAPI rest effectue cette opération sur le routage de type post. Cela est logique dans ce cas, mais votre API personnalisée devrait être flexible en fonction de lrsquoabstraction de la base de données qursquoelle utilise. Vous pouvez utiliser Post, pouvez utiliser des tables personnalisées, pouvez utiliser un système de base de données complètement différent. Ce sont des décisions que je nrsquoaime pas prendre en cours de base. Voici quelques méthodes qui, comme pouvez le voir, sont du type recommandé et que souhaitez utiliser avec les objets WP _ Query et WP Post: la fonction protégée prepare Item for Response ( wp post $item) {
Retour
lsquonamersquo = gt $item gt Post _ title,
« Description» = gt $item gt Post _ Extract,
G)
}
Fonction protégée prepare _ items for Response ( wp Query $QUERY) {
$Object = []
(! Empty ($QUERY gt Post) {
Foreach ($QUERY gt Post composer $post) {
$items [$post gt ID] = $this gt prepare _ item U ($post) for Response
}
}
Renvoie $items
} dans cette classe, jrsquoai ajouté une classe de requête qui ne contient que des requêtes WP _ Queries. La raison en est qursquoà lrsquoavenir, je pourrais sous catégoriser les requêtes WP _ ou supprimer les requêtes WP et je veux être flexible et facile à remplir. Crsquoest pourquoi jrsquoai créé une méthode séparée pour créer des paramètres pour la requête WP _ query. Fonction protégée Query _ args ($type =
$Argo =
lsquopost U typersquo = gt $this gt Post U type,
G)
(! Empty ($page)
$args [lsquoTax Queryrsquo] =
[2]
« classification» = gt « type de produit»,
« champ» = gt « escargot»,
« terme» = gt $type,
Objet qui implémente lrsquointerface. Je peux le faire pour que cette classe puisse obtenir un tableau dans son constructeur et vérifier le contenu du tableau. Jrsquoai pensé que ça sentait mauvais, alors jrsquoai ajouté une méthode pour ajouter des chemins au tableau, et ce gars a présenté son seul argument. Fonctions publiques ajouter _ route (route $route) {
$this gt path [] = $PATH
Puisque lrsquoajout drsquoun objet de routage à cette classe se produit après lrsquoInstanciation de cette classe, jrsquoa i besoin drsquoun moyen de faire défiler le tableau au lieu de le faire dans le constructeur. La méthode boucle simplement le tableau et appelle la méthode add _ routes sur chaque objet. Fonction publique add _ routes () {
(! $this gt Bootstrap amp amp! Empty ($this gt Routing) {
Var route $route
Foreach ($this gt Routing is $Routing)
$route gt Ajouter une route ($this gt namespace)
}
$this gt boot = true
}
Notez que jrsquoutilise une propriété pour empêcher cette méthode drsquoajouter deux routes. Jusqursquoà présent, je nrsquoai relié ce code à aucune opération. Nous avons donc un système complètement isolé qui peut être appelé de diverses façons. Bien sûr, nous voulons charger ce code sur le crochet rest _ API init. Crsquoest le fichier de base du plug in que jrsquoai créé pour cet exemple, qui enregistre un chargeur automatique et crée des instances des classes de chemin et de démarrage sur rest _ API init. appliquez ce système à un plug in ou à un sujet, cela peut ne pas avoir de sens, mais pour un site ou une application spécifique, il peut être très logique de charger une API dans un plug in mu de cette façon. Utiliser Josh API boot
Add _ action (lsquorest API initrsquo, Function () {
http:www.php-fig.orgpsrpsr-4examples
SPL u autoload u Register (Function ($Class) {
Préfixe drsquoespace de noms propre au projet
$préfixe = lsquoJosh API
$base _ dir = Dir. lsquo API »
$Len = strlen ($prefix)
(ST
Rncmp ($prefix, $class, $len) = (0)
Reviens!
}
$relative _ class = substr ($class, $len)
$file = $Basic Directory. Str _ replace (
(File _ exists ($file) {
$File required
}
})
Créer un chemin de produit
$product = new Josh API route PRODUCT ()
OMG (s) shoes! Chaussures
$shows = new Josh API route shows ()
Faire fonctionner lrsquoAPI
$API = nouveau démarrage (lsquoStore v1rsquo)
$API gt Ajouter un chemin ($produit)
$API gt Ajouter un itinéraire (chaussures)
$API gt Ajouter une route ()
}) Il est important de noter qursquoil pourrait en avoir besoin dans drsquoautres circonstances. Par exemple, si nous voulons générer une réponse API sans requête HTTP. Une utilisation potentielle de cette approche est que si nous avons un thème ou une autre interface frontale, nous pouvons travailler à partir drsquoobjets json. Lorsque nous chargeons la page drsquoaccueil, nous pouvons appeler directement le routage et imprimer la réponse json, ou la passer au script wp u localize U. Je mets tout ce code dans le dépôt GIT. Vous pouvez lrsquoajouter au projet tel quel et ajouter votre propre chemin en étendant la classe CRUD et en lrsquoutilisant tel quel. Crsquoest à dire, je encourage à le construire pour répondre à vos besoins. Plus important encore, je encourage à lrsquoutiliser comme exemple de la façon de tirer parti des différentes parties des plug ins, des sujets, des sites Web et des applications et de construire des systèmes autour de fonctionnalités communes. Cet article prend lrsquoAPI rest comme exemple parce qursquoelle est utile et que je connais bien lrsquoAPI rest. De plus, en lisant le Code de la version 2 de lrsquoAPI rest, jrsquoai appris à suivre ces principes de PHP orienté objet pour créer des systèmes faciles à comprendre, extensibles et testables. Je encourage à concevoir différents groupes de fonctions dans votre code de cette façon. Je me retrouve souvent directement dans le Code pour accomplir une tâche. Jrsquoai eu un problème et je lrsquoai résolu. Mais jrsquoai souvent des problèmes similaires.
Je me retrouve à travailler en arrière, à transformer la plupart de ce que je fais en classes abstraites et interfaces, et à commencer à construire des systèmes autour drsquoelles. Commencez par définir le système et forcez à considérer le processus. Cela force à réfléchir à la façon idéale de travailler. La plupart du temps, du point de vue des systèmes répétables, même si cela nrsquoest nécessaire qursquoune seule fois, cela conduit à la création de systèmes meilleurs, plus testables et plus flexibles qui nécessitent moins de remaniement à mesure que les applications grandissent.