În această serie vom analiza utilizarea tabelelor de baze de date personalizate. Vom analiza modul de creare, menținere și eliminare a tabelului, precum și modul de adăugare, eliminare și interogare a datelor în mod sigur și eficient. În acest prim articol ne uităm când tabelele personalizate ar putea fi potrivite, avantajele și dezavantajele utilizării acestora și cum se creează tabelul.
Din fericire, WordPress oferă un API destul de substanțial, care face din crearea și interacțiunea cu tabelele personalizate un pic mai simplu. Mai ales: $ wpdb
clasa și dbDelta ()
funcție pe care o vom vedea mai mult în timpul seriei. Cu toate acestea, crearea unui tabel personalizat înseamnă crearea unui lucru străin WordPress - și pierdeți majoritatea cadrului care înconjoară mesele native. Din acest motiv, dvs. ca autor de pluginuri sunteți responsabili pentru interacțiunea sigură și eficientă cu acesta. Deci, înainte de a sări, trebuie să analizați cu atenție dacă este sau nu mai potrivit să folosiți o masă de bază existentă.
Așa cum am menționat, tabelele personalizate stau în afara cadrului normal WordPress - și, în cea mai mare parte, aceasta este cauza principală a dezavantajelor sale:
Nu există un răspuns "corect" la acest lucru și este necesară o judecată sensibilă a argumentelor pro și contra. Cu toate acestea, secțiunea anterioară prezintă unele neajunsuri grave pentru a nu utiliza schema WordPress existentă - ca atare, dacă nu sunteți sigur, este de obicei cel mai bine să evitați crearea unui tabel. Mai mult, o abordare de masă personalizată necesită o mulțime de lucruri și oferă o șansă amplă pentru bug-uri pentru a accesa cu crawlere. Dar având în vedere acest lucru, atunci când ar putea fi adecvat un tabel personalizat?
Unul dintre argumentele cele mai importante pentru tabelele personalizate este când datele trebuie structurate într-un mod care nu este potrivit pentru tabelele native. * _posts
tabelul este în mod inerent orientat spre posturi și pagini, ceea ce poate fi total inadecvat pentru datele dvs. De fapt, datele dvs. ar putea fi mai bine distribuite pe mai multe tabele, cu relații între ele. S-ar putea să nu fie chiar așa de complicat: pluginul Posturi 2 Posturi utilizează o tabelă personalizată pentru a stoca relații multe-la-multe dintre tipurile de posturi. Acest ar putea se face folosind API-ul de taxonomie (și inițial a fost) sau meta API - dar nici una dintre acestea nu este deosebit de eficientă - și în timp ce poate fi bine pentru site-uri mai mici, nu scade bine. Scribu a mutat Posts 2 la un tabel de implementare personalizat pentru a permite informații despre o relație care urmează să fie stocate.
În timp ce cele mai multe cazuri pot fi "stoarse" în * _posts
mucegai folosind post meta, aceasta nu poate furniza cel mai eficient traseu: Tabelul meta meta folosește o coloană de valori un indexate pentru a stoca datele. Este incredibil de rapidă în preluarea datelor meta de post (WordPress utilizează și cache aici), dar interogările complexe care utilizează tabela meta pot fi ineficiente sau aproape imposibile.
În legătură cu cele de mai sus sunt interogări complexe, pe care tabelele native ar putea să nu fie proiectate să le finalizeze în mod eficient. În organizatorul evenimentului, de exemplu, un eveniment este un post cu datele evenimentului stocate într-un tabel separat. Deși ar fi posibil ca aceste date să fie stocate ca post meta - atunci când evenimentele au mai mult de o dată ar face ca orice interogare bazată pe date să fie extrem de dificilă și ineficientă - în special din moment ce coloana meta-valoare nu este indexată.
Dacă utilizați wp_posts
iar datele dvs. sunt suficient de mari (100.000 de posturi), atunci Mai împiedică performanța, în funcție de ce interogări executați. Acest argument pe cont propriu este destul de slăbit într-adevăr, deoarece există o mulțime de necunoscute care îi vor afecta validitatea. În general însă, bazele de date sunt rapide la ceea ce fac - și cadrul WordPress înconjurător servește la optimizarea interogărilor cât mai mult posibil. În combinație cu ceilalți doi factori, cu toate acestea, puteți găsi că o tabelă personalizată prezintă cea mai sensibilă opțiune.
Odată ce ați decis că este necesară o masă personalizată, trebuie să creați tabelul. Înainte de a face acest lucru, vom stoca numele tabelului nostru personalizat $ wpdb
. Această informație globală conține toate informațiile referitoare la baza de date pentru blogul curent (se va schimba de la site la site, când se utilizează site-ul multi-site). Vom adăuga numele nostru la acest tabel global. Acest lucru nu este deloc necesar, dar face restul codului nostru puțin mai curat:
add_action ('init', 'wptuts_register_activity_log_table', 1); add_action ('switch_blog', 'wptuts_register_activity_log_table'); funcția wptuts_register_activity_log_table () global $ wpdb; $ wpdb-> wptuts_activity_log = "$ wpdb-> prefix wptuts_activity_log";
Codul de mai sus utilizează $ Wpdb-> prefix
pentru a adăuga un prefix la numele tabelului. Prefixul este prestabilit wp_
dar poate fi modificată de utilizatorul din wp-config.php
. Acest lucru este necesar atunci când este posibil să aveți mai mult de o instalare WordPress utilizând aceeași bază de date, dar poate fi schimbată și din alte motive. Ca atare, nu poți presupune că prefixul este wp_
. Ca și în funcții, clase și setări etc, trebuie să vă asigurați că numele tabelului este unic.
În această serie vom reveni la exemplul următor. Ne vom imagina că creăm o tabelă pentru a înregistra activitatea utilizatorilor (actualizarea sau eliminarea postărilor, modificarea setărilor, încărcarea unei imagini etc.).
Există diferite convenții pentru cum vă numiți coloanele (și mesele dvs. pentru asta) - dar indiferent de cum le numiți, este important să fiți consistent. Aș recomanda să folosiți numai caractere minuscule, deoarece în unele situații numele coloanelor pot fi sensibile la minuscule și impunerea acestei reguli face ca greșelile să fie mai puțin probabile și îmbunătățește lizibilitatea. Așa cum vom vedea mai târziu în serie, este de asemenea util pentru când trebuie să coloane de albă. Ar trebui să separați cuvintele din numele coloanelor (de ex. post_data
, POST_CONTENT
) pentru lizibilitate - dar ar trebui să faceți acest lucru cu sublinieri, și nu spații.
De asemenea, ar trebui să evitați cuvintele rezervate. Dacă coloana se referă la o tabelă străină, atunci este recomandat să utilizați numele coloanei străine (cum ar fi numele de utilizator
, exemplul nostru).
În exemplul nostru vom numi coloanele noastre:
log_id
- ID-ul jurnalului.numele de utilizator
- numele de utilizator pentru care corespunde jurnalul.activitate
- activitatea care a avut loc.object_id
- ID-ul obiectului (de exemplu, ID-ul postului, ID-ul utilizatorului, ID-ul comentariului etc.) care a făcut obiectul activității utilizatorului.object_type
- tipul de obiect (de ex. "postare", "utilizator", "comentariu" etc.).activity_date
- data de desfășurare a activității.Înainte de a merge mai departe, va trebui să decideți tipurile de date ale coloanelor pe care le va avea masa. Tipurile de coloane pot fi împărțite în trei categorii: șiruri de caractere, numere numerice și datetime. Pentru fiecare dintre acestea există multe variante. Puteți găsi aici o referință completă.
Este important să alegeți tipul de date corespunzător pentru tabel, deoarece aceasta va afecta eficiența interogărilor dvs. Unele tipuri de date vă permit să setați o limită (de ex. varchar (40)
- care vă permite să stocați până la 40 de caractere). Limita este opțională, dar este recomandată deoarece poate îmbunătăți performanța - deci va trebui să decideți pentru fiecare coloană care este valoarea maximă a caracterelor pe care o va solicita coloana. Notă pentru tipurile de date numerice: lungimea se referă la numărul de cifre - nu la maxim (de ex. INT (10)
permite numere întregi negative de până la 10 cifre - până la 4 294 967 295).
Când stocați date, ar trebui să utilizați întotdeauna DATETIME
tipul de date (stocat ca 2012-11-05 14:55:10) - și cu siguranță nu o reprezentare prietenoasă a omului a datei (de exemplu, 5 noiembrie 2012, 14:55). DATETIME
valorile pot fi ușor formatate în formă ușor de citit de om folosind funcții precum mysql2date ()
. Ar trebui să păstrați datele în fusul orar UTC și, dacă este necesar, să o comutați la o altă fus orar de ieșire.
În exemplul nostru vom avea:
log_id
- bigint (20)numele de utilizator
- bigint (20)activitate
- varchar (20)object_id
- bigint (20)object_type
- varchar (20)Data
- datetimeApoi va trebui să decideți ce coloane să indice - acestea vor fi declarate ca CHEIE
s, dintre care unul va fi CHEIA PRINCIPALA
. Cheia primară este o coloană în care fiecare rând are a unic intrare - de obicei, este vorba doar de un număr întreg de auto-incrementare, în esență "numărul de rând".
Valorile celorlalte coloane indexate nu trebuie să fie unice, dar valoarea ar trebui să determine un set relativ mic de înregistrări. Ideea indexării este de a îmbunătăți interogările citite. Fără un index, o căutare ar trebui să citească întreaga tabelă pentru a găsi rânduri potrivite. Dacă o coloană este indexată și o parte din interogare - atunci ea poate găsi rapid rânduri care se potrivesc acelei coloane și apoi acel subset mai mic de rânduri de potrivire poate verifica în raport cu interogarea (Analogia este un index pentru o carte).
Astfel, dacă nu faceți o interogare de către acea coloană, atunci indexarea acelei coloane nu va ajuta (dacă nu căutați niciodată un cuvânt în indexul cărții, este posibil să nu fie acolo). Nici dacă o mulțime de înregistrări au aceeași valoare, cum ar fi o coloană "gender", deoarece aceasta nu va oferi o îmbunătățire semnificativă pe o scanare de masă completă (imaginați-vă un index de carte care a enumerat un cuvânt care apare pe fiecare altă pagină).
Indexarea nu este gratuită: Coloanele declarate ca CHEIE
s reduce performanța de scriere (pentru a continua analogia pe care ar trebui să o actualizați atunci când un cuvânt indexat este adăugat sau eliminat) - și deci va trebui să decideți care este echilibrul corect pentru configurarea dvs. Mai multe informații pot fi găsite aici.
Deoarece probabil că vom dori să interogăm după utilizator (pentru a vedea activitatea lor recentă) vom indexa această coloană și vom folosi log_id
ca cheie primară.
Vom plasa codul pentru crearea tabelului personalizat în interiorul următoarei funcții:
funcția wptuts_create_tables () // Cod pentru crearea unei tabele merge aici // Creați tabele în activarea pluginului register_activation_hook (__FILE__, 'wptuts_create_tables');
Această funcție va trebui apelată pe cârligul de activare al plugin-ului, precum și oricând dorim să facem modificări ale tabelului - de exemplu, adăugând coloane sau schimbând tipul de date (vom vedea de ce mai târziu în serie).
Faptul că prin utilizarea cârligului de activare, wptuts_create_tables ()
ar putea fi numit atunci când un tabel există deja, nu este o supraveghere - și, din nou, vom acoperi de ce mai târziu în serie.
În interiorul acestei funcții, includem wp-admin / include / upgrade.php pentru a configura câteva constante și pentru a încărca funcția dbDelta ()
. Rețineți că, atunci când un plugin este activat, acesta nu reușește init
cârlig, deci wptuts_register_activity_log_table ()
trebuie să fie chemat manual.
requ_once (ABSPATH. 'wp-admin / include / upgrade.php'); global $ wpdb; global $ charset_collate; // Apelați acest lucru manual deoarece s-ar putea să fi pierdut cârligul init wptuts_register_activity_log_table ();
Global $ charset_collate
conține setul de caractere și colaționarea utilizate de tabelele WordPress native. În mod liber, acestea definesc codificarea caracterelor și modul în care sunt comparate - având în vedere că WordPress este folosit în multe limbi diferite, este important să folosiți colaționarea corectă pentru tabelul.
În afară de colaționare, instrucțiunea SQL ar trebui să declare numele tabelului, împreună cu fiecare coloană, tipul și valoarea implicită și orice altă valoare CHEIE
coloane, inclusiv a CHEIA PRINCIPALA
coloană. De obicei, va avea forma:
CREATE TABLE [numele tabelului] ([coloana cheii primare] bigint (20) nesemnate NOT NULL auto_increment, [numele coloanei] [tipul de date] [implicit], KEY (nume de coloană) ) [colaționare];
Pentru a crea acest tabel, adăugăm următoarele la adresa noastră wptuts_create_tables ()
funcţie:
$ sql_create_table = "CREATE TABLE $ wpdb-> wptuts_activity_log (log_id bigint (20) nesemnificat NOT NULL auto_increment, user_id bigint (20) nesemnificat NOT NULL implicit '0', activitate varchar (20) bigint (20) nesemnate NOT NULL implicit '0', object_type varchar (20) NOT NULL implicit 'post', activity_date datetime NOT NULL implicit '0000-00-00 00:00:00', KEY PRIMARY (log_id), KEY user_id (utilizator_id)) $ charset_collate; "; dbDelta ($ sql_create_table);
dbDelta ()
funcția ne îndeplinește CREATE TABLE
comanda. Poate fi destul de strictă în legătură cu instrucțiunea SQL dată. De exemplu, acolo trebuie sa două spații între CHEIA PRINCIPALA
și coloana cheii primare. iar cheile trebuie să aibă un nume.
Dacă la activare găsiți că primiți "Aveți caracterul X al ieșirii neașteptate ... 'este probabil că există o eroare în instrucțiunea dvs. SQL. Uneori se datorează dbDelta ()
e strict. Dacă adăugați wp_die ();
după dbDelta ()
, acest lucru ucide procesarea și (cu "WP_DEBUG" setat la adevărat) va dezvălui orice mesaje de eroare.
În acest articol am analizat motivele pentru care ar trebui și nu ar trebui să folosiți tabele personalizate, precum și detaliile pe care trebuie să le luați în considerare și, în sfârșit, cum să creați o tabelă. Urmatoarea parte a acestei serii va acoperi sanitizarea, analizarea injectiei SQL si cum sa va protejati de aceasta. Codul din acest articol este disponibil la acest depozit GitHub și va fi actualizat în continuarea seriei.
$ wpdb
clasă