În tutorialul anterior, am acoperit o mulțime de concepte, toate acestea fiind necesare pentru a înțelege pe deplin ce facem în acest tutorial.
Mai exact, am abordat următoarele subiecte:
În unele serii, este ușor să ignorați tutorialele care nu se pot construi unul pe altul; totuși, această serie nu are intenția de a fi așa. În schimb, este destinat să fie citit în ordine succesivă și este menit să se bazeze pe conținutul fiecărui tutorial anterior.
Cu asta a spus că presupun că sunteți prinși.
Chiar dacă aș fi menționat acest lucru în primul tutorial, tot îmi place să fiu sigur că suntem pe aceeași pagină în ceea ce privește ceea ce facem în fiecare tutorial și cu ce software aveți nevoie.
Deci, în acest tutorial, planul este după cum urmează:
În cele din urmă, nu vom scrie mult cod în acest tutorial, dar vom scrie câteva. Este, totuși, un tutorial practic prin faptul că efectuăm analize și design orientate pe obiecte. Aceasta este o etapă necesară pentru multe proiecte de anvergură (și ceva ce ar trebui să se întâmple pentru proiecte de mici dimensiuni).
Dacă ați urmat de-a lungul, ar trebui să fiți deja pregătiți. Dar pentru a vă asigura că este vorba despre versiunea scurtă a tot ceea ce aveți nevoie:
Cu toate acestea, suntem gata să lucrăm la codul partajat în tutorialul anterior. Deci sa începem.
Primul lucru pe care vrem să-l facem este să analizăm starea curentă a autoloaderului nostru. Ar putea părea o mulțime de cod pentru a lipi într-un singur bloc de cod, dar asta în sine ne arată că avem ceva de făcut pentru a face.
Cu asta a spus, iată starea curentă a autoloaderului nostru:
0; $ i--) // Citiți componenta curentă a părții de fișier. $ curent = strtolower ($ file_parts [$ i]); $ curent = str_ireplace ('_', '-', $ curent); // Dacă suntem la prima intrare, atunci suntem la numele fișierului. dacă (numără ($ file_parts) - 1 === $ i) / * Dacă "interfața" este conținută în părțile din numele fișierului, atunci * definește $ file_name diferit, astfel încât să fie încărcat corect. * În caz contrar, trebuie doar să setați $ file_name egal cu cel al structurii de nume * filename *. * / if (strpos (strtolower ($ file_parts [count ($ file_parts) - 1]), 'interfață')) // Luați numele interfeței din numele său calificat. $ nume_intervenție = explode ('_', $ file_parts [count ($ file_parts) - 1]); $ interface_name = $ numele interfeței [0]; $ file_name = "interfață- $ nume_intervenție.php"; altceva $ file_name = "class- $ current.php"; altceva $ namespace = '/'. $ curent. Spațiu de nume $; // Acum construi o cale către fișier folosind maparea în locația fișierului. $ filepath = trailingslashit (dirname (dirname (__FILE__)) $ namespace); $ filepath. = $ nume_fișier; // Dacă fișierul există în calea specificată, atunci includeți-l. dacă (file_exists ($ filepath)) include_once ($ filepath); altceva wp_die (esc_html ("Fișierul care încearcă să fie încărcat la $ filepath nu există"));
În acest moment, rețineți că principiul responsabilității unice prevede următoarele:
O clasă ar trebui să aibă doar un singur motiv pentru a se schimba.
Chiar acum, nu avem nici măcar o clasă, să nu mai vorbim de mai multe metode individuale care au doar un singur motiv să se schimbe.
Și deși ar putea fi logic să începeți prin a rupe această metodă autoloader în metode mai mici, individuale, să începem de la un nivel superior și să începem să ne gândim la un autoloader în termeni de interfață. Apoi vom examina crearea unei clase (sau clase).
Rețineți din tutorialul anterior că o interfață este definită de manualul PHP după cum urmează:
Interfețele de obiecte vă permit să creați un cod care să specifice metodele pe care o clasă trebuie să le implementeze, fără a fi nevoie să definiți modul în care sunt gestionate aceste metode.
Având în vedere codul și definițiile de mai sus, să ne gândim la ceea ce trebuie să facă un autoloader dintr-o perspectivă mai modulară. Mai exact, hai să o împărțim în puncte care reprezintă ceea ce ar putea fi suficient pentru a se schimba. Nu, este posibil să nu folosim toate aceste puncte, dar de aceea se numește analiză. Vom lucra la design mai târziu.
Codul face următoarele:
$ class_name
este un nume de variabilă proastă).Astfel, codul de mai sus nouă lucruri-adică este macar nouă motive să se schimbe - înainte de a-și termina lucrările.
Acest lucru ar trebui să fie de la sine înțeles, dar această funcție particulară este un exemplu perfect că putem refactor să demonstreze analiză orientată pe obiecte, design, interfețe și implementare.
Și aceasta ridică o întrebare: Unde începem chiar?
În acest moment, este corect să spunem că putem începe să facem o analiză orientată pe obiecte - adică să privim ce clase potențiale avem și cum interacționează - având în vedere tot ceea ce am enumerat mai sus. Amintiți-vă, de asemenea, dorim ca principiul responsabilității unice să ne ajute să ne îndrume în luarea deciziilor noastre.
În acest moment, nu suntem îngrijorați de modul în care clasele vor comunica unul cu celălalt. În schimb, ne concentrăm mai mult pe crearea de clase care au un singur motiv de schimbare.
Cu asta am spus că voi oferi un set de clase care ar putea funcționa. Înainte de a merge mai departe, uita-te la ceea ce am făcut și încercați să veniți cu propria listă. Atunci putem compara notele.
Rețineți că ați putea avea o idee mai bună decât cele enumerate mai jos sau puteți lua ceva de la ceea ce am împărtășit. Indiferent, acesta este un exercițiu de învățare. Încercăm să îmbunătățim codul nostru, organizația noastră și, în cele din urmă, să devenim programatori mai buni.
Având în vedere ceea ce am enumerat mai sus, am venit cu următoarele clase:
Si asta e. Acum, clasele terță parte din pluginul nostru trebuie doar să știe despre clasa de autoloader, dar autoloaderul va avea nevoie de cunoștințe despre o altă clasă, iar alte clase vor avea nevoie de cunoștințe despre alte clase.
Acolo sunteți modalități de a face față acestei situații (folosind containerele de injecție de dependență, dar acest lucru depășește scopul acestui proiect). Dar ceea ce ne vom strădui să facem prin codul nostru este să minimizăm cât de multe clase știu unul despre celălalt.
În acest moment, diferiți dezvoltatori, firme, agenții și echipe vor lua o altă abordare a modului în care proiectează sistemul pe care lucrează.
Una dintre cele mai comune metode de a face acest lucru este de a folosi ceva numit diagrama UML. Deși este util, nu este ceva care merită făcut în cadrul acestui tutorial, deoarece va necesita un întreg tutorial pentru a explica toate piesele.
Deci, pentru scopurile tutorialului nostru și din moment ce lucrăm cu un număr atât de mic de coduri, vom încerca să eliminăm modul în care fiecare dintre clasele de mai sus ar putea funcționa înainte de a le implementa. În acest fel, vom avea o idee despre cum putem organiza codul nostru.
Rețineți că nu vom fi numiți încă niciunul din acest cod și niciunul din acest cod nu ar trebui implementat sau testat încă de la WordPress. Vom intra în asta în următorul tutorial.
Să începem cu Autoloader
și lucrează de acolo.
Rețineți că această clasă este responsabilă pentru includerea dosarului necesar. Acesta este fișierul care va fi înregistrat cu spl_autoload_register
funcţie.
namespace_validator = nou NamespaceValidator (); $ this-> file_registry = noul FileRegistry (); încărcarea funcției publice ($ filename) if ($ this-> namespace_validator-> is_valid ($ filename)) $ this-> file_registry-> load (numele fișierului $);
Rețineți că această clasă depinde de NamespaceValidator
si FileRegistry
clasă. Vom vedea mai multe detalii în câteva minute.
Acest fișier va analiza numele de fișier primit și va determina dacă este valid. Acest lucru se realizează prin examinarea spațiilor de nume din numele fișierului.
Dacă fișierul face de fapt aparțin spațiului nostru de nume, atunci putem presupune că este sigur să încărcăm fișierul nostru.
FileInvestigator
Această clasă face destul de mult de lucru, deși o parte din ea se face prin metode foarte simple, foarte mici de ajutor. Pe parcursul executării, acesta examinează tipul fișierului pe care a trecut-o.
Apoi, acesta va prelua numele de fișier complet calificat pentru tipul de fișier.
get_file_name ($ file_parts, $ curent, $ i); dacă (numără ($ file_parts) - 1! == $ i) $ filepath = trailingslashit ($ filepath); retur $ filepath; funcția privată get_file_name ($ file_parts, $ current, $ i) $ filename = "; if (count ($ file_parts) - 1 === $ i) if ($ this-> is_interface ($ file_parts) fișier nume = $ this-> get_interface_name ($ file_parts); altceva $ filename = $ this-> get_class_name ($ curent); altceva $ filename = $ this-> get_namespace_name ($ curent); funcția privată is_interface ($ file_parts) retur strpos (strtolower ($ file_parts [count ($ file_parts) - 1]), 'interfață' $ file_parts [count ($ file_parts) - 1]); $ interface_name = $ interface_name [0]; return "interface- $ interface_name.php"; funcția privată get_class_name ($ current) return "class- $ current.php" ; funcția privată get_namespace_name ($ curent) return '/'. $ current;Dacă există un fișier care poate fi refactat un pic mai mult, atunci acesta este. La urma urmei, încearcă să determine dacă lucrăm cu o clasă, o interfață sau o clasă. O fabrică simplă ar putea fi mai potrivită pentru acest lucru.
Când vine timpul să punem în aplicare codul nostru, probabil că vom refactoriza acest lucru mai departe. Până atunci, acesta este un proiect preliminar care poate funcționa destul de bine.
FileRegistry
Aceasta va folosi calea fișierului complet calificată și va include fișierul; în caz contrar, va folosi API-ul WordPress pentru a afișa un mesaj de eroare.
clasa FileRegistry private $ investigator; funcția publică __construct () $ this-> investigator = new FileInvestigator (); încărcarea funcției publice ($ filepath) $ filepath = $ this-> investigator-> get_filetype ($ filepath); $ filepath = rtrim (plugin_dir_path (dirname (__FILE__)), '/'). $ Filepath; dacă (file_exists ($ filepath)) include_once ($ filepath); altceva wp_die (esc_html ('Fișierul specificat nu există.'));O altă alternativă la utilizarea API-ului WordPress ar fi aruncarea unui mesaj de excepție personalizat. În acest fel, vom putea separa complet sau decupla codul nostru de la WordPress.
Încă o dată, acest cod este o transmisie de la autoloaderul inițial. În timpul implementării, putem schimba și acest lucru.
Concluzie
Bine, deci ne-am uitat la codul existent pentru autoloader-ul nostru, și apoi am stubat un cod potențial pe care îl putem folosi pe baza unor analize și design orientate pe obiecte.
Este soluția la care lucrăm mai bine decât ceea ce avem? Absolut. Aceasta va funcționa în contextul WordPress și al plugin-ului nostru existent? Nu vom ști până când nu vom începe să conectăm acest plugin la pluginul nostru.
După cum am menționat anterior, există încă unele zone în care am putea refactoriza acest cod. Dacă vom lovi aceste tipuri de probleme atunci când implementăm codul nostru în versiunea finală a plugin-ului nostru, vom analiza exact ceea ce facem.
Indiferent de situație, codul pe care îl avem acum ar trebui să fie mai ușor de citit (deși încă mai avem DocBlocks și câteva comentarii inline de introdus) și mai susținute și chiar mai teste.
Cu toate acestea, sper că acest lucru ți-a dat o idee despre modul de a lua o metodă lungă și ao sparge în mai multe cursuri conduse de scopuri. Sigur, având mai multe clase ar putea să se simtă ciudat la început, dar asta nu înseamnă că este un lucru rău. Aveți mai multe fișiere (și astfel clase) cu un cod mai mic decât un fișier cu o mulțime de cod este mai bine.
Îmbrățișează natura contraintuitivă a programării orientate pe obiecte în această privință. În tutorialul următor, ne vom întoarce la pluginul nostru și vom lucra la implementarea unei variații a codului de mai sus. Probabil că vom depana și câteva dintre ele. La urma urmei, rareori ne facem bine prima data
Până atunci, dacă sunteți interesat să citiți mai multe despre programarea orientată obiect în contextul WordPress, puteți găsi toate tutorialele mele anterioare pe pagina mea de profil. Simțiți-vă liber să urmați pe blogul meu sau urmați-mă pe Twitter unde vorbesc frecvent despre ambele.
Resurse