Tilpassede databasetabeller Opprette tabellen

I denne serien ser vi på bruk av egendefinerte databasetabeller. Vi dekker hvordan du oppretter, vedlikeholder og fjerner tabellen, samt hvordan du trygt og effektivt legger til, fjerner og spørrer data. I denne første artikkelen ser vi på når tilpassede tabeller kan være hensiktsmessige, fordeler og ulemper med å bruke dem og hvordan du lager bordet.

Heldigvis gir WordPress en ganske betydelig API som gjør å skape og samhandle med egendefinerte tabeller litt enklere. Mest spesielt: $ wpdb klasse og dbDelta () funksjon som vi ser mer av under serien. Til tross for det, men å skape et tilpasset bord betyr det å skape noe fremmed til WordPress - og du mister det meste av rammen som omgir de opprinnelige tabellene. Derfor er du som pluginforfatteren ansvarlig for sikker og effektiv samhandling med den. Så før du hopper inn, må du nøye vurdere om det er mer hensiktsmessig å bruke et eksisterende kjernebord.


Ulempene ved å bruke et tilpasset bord

Som nevnt er egendefinerte tabeller satt utenfor det vanlige WordPress-rammeverket, og for det meste er dette den underliggende årsaken til ulempene:

  • Det finnes ingen innfødte tilleggs-, fjern-, oppdaterings- eller spørringsfunksjoner som kan kommunisere med bordet.
  • UI må bygges fra (nesten) grunnen.
  • Sanitering og caching er opp til deg (selv om WordPress gir mye hjelp i dette henseende).
  • Andre plugins, og WordPress seg selv, ikke "forvent" bordet ditt for å være der. På den annen side, hvis dataene dine er en egendefinert innleggstype, vil de fleste velbygde tredjepartsplugger jobbe langs siden.
  • WordPress - eller mange andre relaterte plugins - vil sikkerhetskopiere eller eksportere bordet ditt. (Egentlig ganske få backup plugins støtter ikke-core tabeller, men eksport / import er ikke så grei)
  • Du er ansvarlig for å sette opp strukturen til egendefinerte bord (er) på den mest effektive måten, inkludert å velge den mest passende datatypen for kolonnene.
  • Du er ansvarlig for å skrive feilfrie og effektive SQL-spørringer.

Når skaper en tilpasset tabell passende?

Det er ikke noe "riktig" svar på dette, og fornuftig vurdering av fordeler og ulemper er nødvendig. Men den forrige delen beskriver noen alvorlige ulemper ved ikke å bruke det eksisterende WordPress-skjemaet. Som sådan, hvis du er usikker, er det vanligvis best å unngå å lage et bord. Videre krever en tilpasset tabell tilnærming mye arbeid, og gir rikelig med muligheter for at bugs skal krype inn. Men med det i tankene, når kan et tilpasset bord være passende?

Datastrukturen

En av de viktigste argumentene for egendefinerte tabeller er når dataene må struktureres på en slik måte at det er upassende for de opprinnelige tabellene. De * _posts Tabellen er i utgangspunktet rettet mot innlegg og sider, noe som kan være helt uegnet for dine data. Faktisk kan dataene dine best fordeles over flere tabeller, med forhold mellom dem. Det kan ikke engang være så komplisert: Innlegg 2 Innlegg-plugin bruker et tilpasset bord for å lagre mange til mange relasjoner mellom posttyper. Dette kunne gjøres ved hjelp av taksonomi API (og opprinnelig var) eller meta API - men ingen av disse er spesielt effektive - og mens det kan være bra for mindre områder, skal det ikke skales godt. Scribu flyttet Innlegg 2 Innlegg til en tilpasset tabellimplementering for å tillate informasjon om et forhold som skal lagres.

Mens de fleste tilfeller kan "klemmes" inn i * _posts mugg ved bruk av postmeta, kan dette ikke gi den mest effektive ruten: Postmetabellen bruker en unindeksert verdi kolonne for å lagre data. Det er utrolig raskt å hente et innleggs metadata (WordPress benytter caching her også), men komplekse spørringer ved hjelp av metabordet kan være ineffektive eller nesten umulige.

Komplekse spørringer

I tilknytning til det ovenfor er komplekse spørringer, som de innfødte tabellene kanskje ikke er utformet for å fullføre effektivt. I Event Organizer, for eksempel, er et arrangement et innlegg med hendelsesdatoer lagret i et eget bord. Selv om det vil være mulig å lagre disse datoene som innleggsmeta - gjør det når hendelser har mer enn en dato, vil det være svært vanskelig og ineffektiv å gjøre datagrunnlagsspørsmål - spesielt siden metaverdikolonnen ikke er indeksert.

Scale

Hvis du bruker wp_posts og dataene dine er tilstrekkelig store (100 000 + innlegg) så det kan hindrer ytelse, avhengig av hvilke spørsmål du kjører. Dette argumentet i seg selv er ganske svakt, da det er mange ukjente som vil påvirke dens gyldighet. Generelt er databaser rask på hva de gjør - og det omkringliggende WordPress-rammene tjener til å optimere spørringer så mye som mulig. I kombinasjon med de to andre faktorene kan du imidlertid finne ut at et tilpasset bord presenterer det mest fornuftige alternativet.


Opprette bordet

Når du har bestemt deg for at et tilpasset bord er nødvendig, må vi opprette bordet. Før vi gjør det lagrer vi navnet på vårt egendefinerte bord i $ wpdb. Denne globale inneholder all informasjon om databasen for den nåværende bloggen (den vil endres fra nettsted til nettsted, når du bruker multi-site). Vi legger til vårt tabellnavn på dette globale. Dette er ikke nødvendig, men gjør resten av koden litt finere:

 add_action ('init', 'wptuts_register_activity_log_table', 1); add_action ('switch_blog', 'wptuts_register_activity_log_table'); funksjon wptuts_register_activity_log_table () global $ wpdb; $ wpdb-> wptuts_activity_log = "$ wpdb-> prefix wptuts_activity_log"; 

Ovennevnte kode bruker $ Wpdb-> prefiks for å legge til et prefiks i tabellnavnet. Prefikset er som standard wp_ men kan endres av brukeren i wp-config.php. Dette er nødvendig når du kanskje har mer enn én WordPress-installasjon ved hjelp av samme database, men kan også endres av andre grunner. Som sådan kan du ikke anta at prefikset er wp_. Som med funksjoner, klasser og innstillinger osv., Bør du sørge for at tabellnavnet ditt er unikt.

Gjennom hele denne serien kommer vi tilbake til følgende eksempel. Vi kan tenke oss at vi lager et bord for å logge brukeraktivitet (oppdatering eller fjerning av innlegg, endring av innstillinger, opplasting av et bilde osv.).

Kolonne navnekonvensjoner

Det er forskjellige konvensjoner for hvordan du navngir kolonnene dine (og bordene dine for den saks skyld) - men uansett hvordan du heter dem, er det viktig å være konsistent. Jeg vil anbefale å bruke bare små bokstaver som i noen situasjoner kan kolonneavn være saksfølsomme, og å pålegge den regelen gjør feil mindre sannsynlig og forbedrer lesbarheten. Som vi ser senere i serien, er det også nyttig når du trenger hviteliste kolonner. Du bør skille ord i kolonnenavn (f.eks. post_data, POST_CONTENT) for lesbarhet - men du bør gjøre dette med understreker, og aldri mellomrom.

Du bør også unngå reserverte ord. Hvis kolonnen refererer til et utenlandstabell, anbefales det at du bruker den utenlandske kolonnenes navn (for eksempel bruker-ID, vårt eksempel).

I vårt eksempel skal vi navngi våre kolonner:

  • log_id - logg-IDen.
  • bruker-ID - bruker-IDen som loggen svarer til.
  • aktivitet - aktiviteten som skjedde.
  • object_id - IDen til objektet (for eksempel post-ID, bruker-ID, kommentasjons-ID osv.) som var gjenstand for brukerens aktivitet.
  • objekt - typen objekt (for eksempel 'innlegg', 'bruker', 'kommentar' etc).
  • activity_date - Aktivitetens datetime.

Bestemmer kolonnetyper

Før du går videre, må du avgjøre datatyper av kolonnene ditt bord skal ha. Kolonne typer kan deles inn i tre kategorier: strenger, numerikk og datatider. For hver av disse er det mange varianter. Her finner du en fullstendig referanse.

Det er viktig å velge riktig datatype for bordet ditt, da dette vil påvirke effektiviteten av dine spørsmål. Noen datatyper lar deg sette en grense (f.eks. varchar (40) - som lar deg lagre opptil 40 tegn). Grensen er valgfri, men anbefales fordi det kan forbedre ytelsen - så du må bestemme for hver kolonne hva det maksimale antall tegn som kolonnen vil kreve. Merk for numeriske datatyper lengden refererer til antall sifre - ikke maksimum (f.eks. INT (10) tillater ikke-negative heltall på opptil 10 siffer - så opp til 4.294.967.295).

Når du lagrer datoer, bør du nesten alltid bruke DATO TID datatype (lagret som 2012-11-05 14:55:10) - og absolutt ikke en menneskelig vennlig representasjon av datoen (for eksempel 5. november 2012 14:55). DATO TID verdier kan enkelt formateres i menneskelig lesbar form ved hjelp av funksjoner som mysql2date (). Du bør lagre datoer i UTC tidszone og om nødvendig bytte den til en annen tidszone på utgang.

I vårt eksempel har vi:

  • log_id - bigint (20)
  • bruker-ID - bigint (20)
  • aktivitet - varchar (20)
  • object_id - bigint (20)
  • objekt - varchar (20)
  • Dato - dato tid

Indeksere kolonner

Deretter må du bestemme hvilke kolonner som skal indekseres - disse blir deklarert som NØKKELs, hvorav en vil være PRIMÆRNØKKEL. Den primære nøkkelen er en kolonne hvor hver rad har a unik oppføring - vanligvis er det bare et automatisk økende heltall, i hovedsak "radnummeret".

Verdiene av de andre indekserte kolonnene behøver ikke være unike, men verdien skal bestemme et relativt lite sett med poster. Ideen om indeksering er å forbedre leseforespørsler. Uten en indeks ville et søk måtte lese gjennom hele bordet for å finne matchende rader. Hvis en kolonne er indeksert og en del av spørringen - så kan den raskt finne rader som samsvarer med den kolonnen, og så kan det mindre delmengden av matchende rader kontrolleres mot spørringen (Analogen er en indeks for en bok).

Som sådan hvis du ikke spørre etter den kolonnen, vil ikke indeksering av den kolonnen hjelpe (hvis du aldri ser opp et ord i bokens indeks, kan det heller ikke være der). Heller ikke hvis mange poster deler samme verdi, som for eksempel en "kjønn" -kolonne, da dette ikke vil gi mye av en forbedring på en fullstendig bordskanning (forestill deg en boksindeks som angir et ord som vises på hver annen side).

Indeksering er heller ikke gratis: Kolonner erklært som NØKKELs redusere skriveytelsen (for å fortsette analogien du trenger for å oppdatere bokindeksen når et indeksert ord er lagt til eller fjernet) - og så må du bestemme hva den riktige balansen er for oppsettet. Mer informasjon finner du her.

Siden det er sannsynlig at vi vil spørre av brukeren (for å se deres siste aktivitet), indekserer vi denne kolonnen, og bruker log_id som primærnøkkel.

Opprette bordet

Vi legger koden for å lage det egendefinerte bordet inne i følgende funksjon:

 funksjon wptuts_create_tables () // Koden for å lage en tabell går her // Opprett tabeller på plugin aktivering register_activation_hook (__FILE__, 'wptuts_create_tables');

Denne funksjonen må kalles på pluginets aktiveringskrok, samt når vi ønsker å gjøre noen endringer i tabellen - for eksempel legge til kolonner eller endre datatypen (vi vil dekke hvorfor senere i serien).

Det faktum at ved å bruke aktiveringskroken, wptuts_create_tables () kan kalles når et bord allerede eksisterer, er ikke et tilsyn - og igjen vil vi dekke hvorfor senere i serien.

Innenfor den funksjonen inkluderer vi wp-admin / includes / upgrade.php å sette opp noen konstanter og laste funksjonen dbDelta (). Merk at når et plugin er aktivert, savner det i det krok, så wptuts_register_activity_log_table () må kalles manuelt.

 require_once (ABSPATH. 'wp-admin / includes / upgrade.php'); global $ wpdb; global $ charset_collate; // Ring dette manuelt som vi kanskje har savnet init-kroken wptuts_register_activity_log_table ();

Den globale $ charset_collate inneholder tegnsettet og sorteringen som brukes av de innfødte WordPress-tabellene. Løst definerer disse kodene for tegn og hvordan de sammenlignes - gitt at WordPress brukes på mange forskjellige språk, er det viktig å bruke riktig sortering for bordet ditt.

Bortsett fra sorteringen, bør SQL-setningen deklarere tabellnavnet, sammen med hver kolonne, dens type og standardverdi og eventuelle NØKKEL kolonner, inkludert a PRIMÆRNØKKEL kolonne. Vanligvis vil det være av skjemaet:

 CREATE TABLE [tabellnavn] ([primærnøkkelkolonne] bigint (20) usignert IKKE NULL auto_increment, [kolonnenavn] [datatype] [standard], PRIMARY KEY ([kolonnenavn]), nøkkelnavn ) [sortering];

For å lage denne tabellen legger vi til følgende i vår wptuts_create_tables () funksjon:

 $ sql_create_table = "CREATE TABLE $ wpdb-> wptuts_activity_log (log_id bigint (20) usignert IKKE NULL auto_increment, user_id bigint (20) unsigned IKKE NULL standard '0', aktivitet varchar (20) IKKE NULL standard 'oppdatert', objekt_id bigint (20) unsigned IKKE NULL standard '0', object_type varchar (20) IKKE NULL standard 'post', activity_date datetime IKKE NULL standard '0000-00-00 00:00:00', PRIMARY KEY (log_id), KEY user_id (user_id)) $ charset_collate; "; dbDelta ($ sql_create_table);

De dbDelta () funksjonen utfører vår CREATE TABLE kommando. Det kan være ganske streng om SQL-setningen gitt til den. For eksempel, der to mellomrom mellom PRIMÆRNØKKEL og primærnøkkelkolonnen. og nøkler må gis et navn.

debugging

Hvis du ved aktivering finner du at du får "Du har X tegn på uventet produksjon ... 'feilmelding - det er sannsynlig at det er en feil i SQL-setningen. Noen ganger skyldes det dbDelta ()s strenghet. Hvis du legger til wp_die (); etter dbDelta (), dette dreper behandlingen og (med 'WP_DEBUG' satt til true) vil avsløre eventuelle feilmeldinger.

Sammendrag

I denne artikkelen har vi sett på grunner til hvorfor du bør og bør ikke bruke egendefinerte tabeller, samt detaljene du må vurdere og endelig hvordan du lager et bord. Den neste delen av denne serien vil dekke sanitering, se på SQL-injeksjon og hvordan du beskytter deg mot det. Koden i denne artikkelen er tilgjengelig på dette GitHub-depotet, og vil bli oppdatert ettersom serien fortsetter.


ressurser

  • MYSQL: Datatyper
  • MYSQL: Reserverte vilkår for kolonner og talbes
  • MYSQL: Indekser
  • Introduksjon til MySQL
  • Codex: Opprette tabeller med plugger
  • Codex: $ wpdb klasse