In deze serie zullen we kijken naar het gebruik van aangepaste databasetabellen. We bespreken hoe u de tabel kunt maken, onderhouden en verwijderen, en hoe u veilig en efficiënt gegevens kunt toevoegen, verwijderen en opvragen. In dit eerste artikel bekijken we wanneer aangepaste tabellen geschikt kunnen zijn, de voor- en nadelen van het gebruik ervan en het maken van de tabel.
Gelukkig biedt WordPress een redelijk substantiële API die het maken en gebruiken van aangepaste tabellen een beetje eenvoudiger maakt. Met name: de $ wpdb
klasse en de dbDelta ()
functie waarvan we meer zullen zien tijdens de serie. Desondanks betekent het maken van een aangepaste tabel iets buitenaards creëren voor WordPress - en je verliest het grootste deel van het framework rond de native tabellen. Om die reden bent u als auteur van de plug-in verantwoordelijk voor een veilige en efficiënte interactie ermee. Dus voordat u naar binnen springt, moet u goed overwegen of het al dan niet meer geschikt is om een bestaande kerntafel te gebruiken.
Zoals eerder vermeld, bevinden aangepaste tabellen zich buiten het normale WordPress-raamwerk - en voor het grootste deel is dit de onderliggende oorzaak van de nadelen:
Hier is geen 'goed' antwoord op en een verstandig oordeel over de voor- en nadelen is vereist. In de vorige sectie worden enkele ernstige nadelen geschetst om het bestaande WordPress-schema niet te gebruiken. Als u het niet zeker weet, is het meestal het beste om te voorkomen dat u een tabel maakt. Bovendien vereist een aangepaste tafelbenadering veel werk en biedt het volop gelegenheid voor bugs om in te kruipen. Maar met dat in gedachten, wanneer kan een aangepaste tabel geschikt zijn??
Een van de belangrijkste argumenten voor aangepaste tabellen is wanneer de gegevens zodanig moeten worden gestructureerd dat ze niet geschikt zijn voor de native tabellen. De * _posts
tabel is inherent gericht op berichten en pagina's, die mogelijk totaal ongeschikt zijn voor uw gegevens. In feite kunnen uw gegevens het best verspreid zijn over verschillende tabellen, met onderlinge relaties. Het is misschien niet eens zo ingewikkeld: de plug-in Posts 2 Posts gebruikt een aangepaste tabel om veel-op-veel relaties tussen berichttypen op te slaan. Deze kon worden gedaan met behulp van de taxonomie-API (en was oorspronkelijk) of de meta-API - maar geen van beide zijn bijzonder efficiënt - en hoewel het prima kan zijn voor kleinere sites, schaalt het niet goed. Scribu heeft 2 berichten verplaatst naar een aangepaste tabelimplementatie om informatie over een relatie te kunnen opslaan.
Hoewel de meeste gevallen kunnen worden 'geperst' in de * _posts
matrijs met behulp van post-meta, dit levert mogelijk niet de meest efficiënte route op: de post-metatabel gebruikt een kolom met niet-geïndexeerde waarden om gegevens op te slaan. Het is ongelooflijk snel in het ophalen van metadata van een bericht (WordPress gebruikt hier ook caching) maar complexe query's met behulp van de metatabel kunnen inefficiënt of bijna onmogelijk zijn.
Gerelateerd aan het bovenstaande zijn complexe query's, die de native tabellen mogelijk niet zijn ontworpen om efficiënt te voltooien. In de gebeurtenisorganisator is een gebeurtenis bijvoorbeeld een bericht met afspraakdatums die in een afzonderlijke tabel zijn opgeslagen. Hoewel het mogelijk zou zijn om die datums op te slaan als meta-meta - wanneer gebeurtenissen meer dan één datum hebben, zijn op datum gebaseerde zoekopdrachten buitengewoon moeilijk en inefficiënt - met name omdat de kolom meta-waarde niet is geïndexeerd.
Als je gebruikt wp_posts
en je gegevens zijn voldoende groot (100.000+ berichten) en dan mei belemmeren de prestaties, afhankelijk van welke zoekopdrachten u uitvoert. Dit argument op zichzelf is vrij zwak, want er zijn veel onbekenden die de geldigheid ervan beïnvloeden. Over het algemeen zijn databases echter snel in wat ze doen - en het omringende WordPress-framework dient om vragen zo veel mogelijk te optimaliseren. In combinatie met de andere twee factoren is het echter mogelijk dat een aangepaste tabel de meest verstandige optie is.
Zodra u hebt besloten dat een aangepaste tabel nodig is, moeten we de tabel maken. Voordat we dat doen, slaan we de naam van onze aangepaste tabel op $ wpdb
. Deze globale bevat alle informatie met betrekking tot de database voor de huidige blog (deze zal van site naar site veranderen bij gebruik van multi-site). We zullen onze tabelnaam hieraan toevoegen. Dit is helemaal niet nodig, maar maakt de rest van onze code net iets netter:
add_action ('init', 'wptuts_register_activity_log_table', 1); add_action ('switch_blog', 'wptuts_register_activity_log_table'); function wptuts_register_activity_log_table () global $ wpdb; $ wpdb-> wptuts_activity_log = "$ wpdb-> prefix wptuts_activity_log";
De bovenstaande code gebruikt $ Wpdb-> voorvoegsel
om een voorvoegsel toe te voegen aan de tabelnaam. Het voorvoegsel is standaard wp_
maar kan binnen door de gebruiker worden veranderd wp-config.php
. Dit is nodig als u meer dan één WordPress-installatie met dezelfde database kunt uitvoeren, maar deze kan ook om andere redenen worden gewijzigd. Als zodanig kunt u niet aannemen dat het voorvoegsel is wp_
. Net als bij functies, klassen en instellingen, enz., Moet u ervoor zorgen dat uw tabelnaam uniek is.
In deze reeks komen we terug op het volgende voorbeeld. We zullen ons voorstellen dat we een tabel maken om gebruikersactiviteiten te loggen (berichten bijwerken of verwijderen, instellingen wijzigen, een afbeelding uploaden, enz.).
Er zijn verschillende conventies voor de manier waarop u uw kolommen een naam geeft (en uw tabellen), maar ongeacht hoe u ze noemt, het is belangrijk om consequent. Ik raad aan om alleen kleine letters te gebruiken, omdat in sommige situaties kolomnamen hoofdlettergevoelig kunnen zijn en het opleggen van die regel fouten minder waarschijnlijk maakt en de leesbaarheid verbetert. Zoals we later in de reeks zullen zien, is het ook handig wanneer kolommen moeten worden gewist. U moet woorden in kolomnamen (bijv. post_data
, POST_CONTENT
) voor leesbaarheid - maar u moet dit doen met onderstrepingstekens, en nooit ruimten.
Je moet ook gereserveerde woorden vermijden. Als de kolom verwijst naar een buitenlandse tabel, is het raadzaam de naam van die buitenlandse kolom te gebruiken (zoals gebruikersnaam
, ons voorbeeld).
In ons voorbeeld noemen we onze kolommen:
log_id
- de log-ID.gebruikersnaam
- de gebruikers-ID voor wie het logboek overeenkomt.activiteit
- de activiteit die heeft plaatsgevonden.object_id
- de ID van het object (bijvoorbeeld post-ID, gebruikers-ID, commentaar-ID enz.) die het onderwerp was van de activiteit van de gebruiker.object type
- het type object (bijvoorbeeld 'post', 'gebruiker', 'reactie', enzovoort).activity_date
- de datetime van de activiteit.Voordat u verder gaat, moet u de gegevenstypen bepalen van de kolommen die uw tabel zal hebben. Kolomtypes kunnen in drie categorieën worden opgesplitst: strings, numerieke waarden en datimes. Voor elk van deze zijn er veel varianten. Je kunt hier een volledige referentie vinden.
Het is belangrijk om het juiste gegevenstype voor uw tabel te kiezen, omdat dit van invloed is op de efficiëntie van uw vragen. Met sommige gegevenstypen kunt u een limiet instellen (bijv. VARCHAR (40)
- waarmee u maximaal 40 tekens kunt opslaan). De limiet is optioneel, maar wordt aanbevolen omdat dit de prestaties kan verbeteren. U moet daarom voor elke kolom bepalen wat het maximale aantal tekens is dat de kolom nodig heeft. Opmerking voor numerieke gegevenstypen de lengte verwijst naar het aantal cijfers - niet het maximum (bijv. INT (10)
staat niet-negatieve gehele getallen van maximaal 10 cijfers toe - dus tot 4.294.967.295).
Bij het opslaan van datums moet je bijna altijd de DATUM TIJD
gegevenstype (opgeslagen als 2012-11-05 14:55:10) - en zeker geen mensvriendelijke weergave van de datum (bijvoorbeeld 5 november 2012 14:55 uur). DATUM TIJD
waarden kunnen eenvoudig worden opgemaakt in menselijk leesbare vorm met behulp van functies zoals mysql2date ()
. U moet datums in de UTC-tijdzone opslaan en deze indien nodig naar een andere tijdzone op de uitvoer schakelen.
In ons voorbeeld hebben we:
log_id
- bigint (20)gebruikersnaam
- bigint (20)activiteit
- VARCHAR (20)object_id
- bigint (20)object type
- VARCHAR (20)datum
- datum TijdVervolgens moet u beslissen welke kolommen moeten worden geïndexeerd - deze worden als gedeclareerd SLEUTEL
s, waarvan er één de HOOFDSLEUTEL
. De primaire sleutel is een kolom waarin elke rij een heeft uniek invoer - meestal is het gewoon een auto-verhogend geheel getal, in wezen het 'rijnummer'.
De waarden van de andere geïndexeerde kolommen hoeven niet uniek te zijn, maar de waarde moet een relatief kleine set records bepalen. Het idee van indexeren is om leesvragen te verbeteren. Zonder een index zou een zoekopdracht de hele tabel moeten doorlopen om overeenkomende rijen te vinden. Als een kolom is geïndexeerd en deel uitmaakt van de query, kan deze snel rijen vinden die overeenkomen met die kolom en vervolgens kan die kleinere subset van overeenkomende rijen worden vergeleken met de query (De analogie is een index voor een boek).
Als je dus niet naar die kolom vraagt, zal het indexeren van die kolom niet helpen (als je nooit een woord opzoekt in de index van het boek, kan het er net zo goed niet zijn). Noch als veel records dezelfde waarde delen, zoals een kolom 'gender', omdat dit niet veel van een verbetering van een volledige tabelscan oplevert (stel je een boekindex voor die een woord vermeldt dat op elke andere pagina wordt weergegeven).
Indexering is ook niet gratis: kolommen gedeclareerd als SLEUTEL
s verminderen de schrijfprestaties (om door te gaan met de analogie die je nodig hebt om de boekenindex bij te werken als een geïndexeerd woord wordt toegevoegd of verwijderd) - en dus moet je beslissen wat de juiste balans is voor je opstelling. Meer informatie is hier te vinden.
Aangezien het waarschijnlijk is dat we willen zoeken op gebruiker (om hun recente activiteit te zien), indexeren we deze kolom en gebruiken we de log_id
als de primaire sleutel.
We plaatsen de code voor het maken van de aangepaste tabel binnen de volgende functie:
functie wptuts_create_tables () // Code voor het maken van een tabel gaat hier // Maak tabellen over plugin-activering register_activation_hook (__FILE__, 'wptuts_create_tables');
Deze functie moet worden aangeroepen op de activeringshaak van de plug-in, en op elk moment dat we wijzigingen in de tabel willen aanbrengen - bijvoorbeeld kolommen toevoegen of hun gegevenstype wijzigen (we zullen later in de reeks uitleg geven over waarom).
Het feit dat door het gebruik van de activeringshaak, wptuts_create_tables ()
kan worden aangeroepen wanneer een tafel al bestaat, is geen overzicht - en nogmaals, we zullen later in de serie uitleggen waarom.
Binnen die functie omvatten we wp-admin / includes / upgrade.php om een paar constanten in te stellen en de functie te laden dbDelta ()
. Merk op dat wanneer een plug-in wordt geactiveerd, deze de. Mist in het
haak, dus wptuts_register_activity_log_table ()
moet handmatig worden gebeld.
require_once (ABSPATH. 'wp-admin / includes / upgrade.php'); globale $ wpdb; globale $ charset_collate; // Bel dit handmatig omdat we mogelijk de init hook wptuts_register_activity_log_table () hebben gemist;
Het globaal $ charset_collate
bevat de tekenset en sortering die worden gebruikt door de native WordPress-tabellen. Los daarvan definiëren deze de coderingen van tekens en hoe ze worden vergeleken - aangezien WordPress in veel verschillende talen wordt gebruikt, is het belangrijk om de juiste sortering voor uw tabel te gebruiken.
Afgezien van de collatie, moet de SQL-instructie de tabelnaam, samen met elke kolom, het type en de standaardwaarde en eventuele declareren SLEUTEL
kolommen, inclusief een HOOFDSLEUTEL
kolom. Typisch zal het van de vorm zijn:
MAAK TAFEL [tabelnaam] ([primary key column] bigint (20) unsigned NOT NULL auto_increment, [kolomnaam] [gegevenstype] [standaard], PRIMAIRE SLEUTEL ([kolomnaam]), KEY key_name ([kolomnaam]) ) [collatie];
Om deze tabel te maken, voegen we het volgende toe aan onze wptuts_create_tables ()
functie:
$ sql_create_table = "MAAK TABLE aan $ wpdb-> wptuts_activity_log (log_id bigint (20) unsigned NOT NULL auto_increment, user_id bigint (20) unsigned NOT NULL default '0', activity varchar (20) NOT NULL standaard 'updated', object_id bigint (20) niet ondertekend NIET NULL standaard '0', objectsoort varchar (20) NOT NULL standaard 'post', activity_date datetime NOT NULL standaard '0000-00-00 00:00:00', PRIMARY KEY (log_id), KEY user_id (user_id)) $ charset_collate; "; dbDelta ($ sql_create_table);
De dbDelta ()
functie voert onze CREËER TAFEL
commando. Het kan vrij strikt zijn over de SQL-instructie die eraan wordt gegeven. Bijvoorbeeld daar moet twee ruimtes tussen HOOFDSLEUTEL
en de kolom met primaire sleutels. en sleutels moeten een naam krijgen.
Als je bij activatie merkt dat je de 'Je hebt het X-teken van onverwachte uitvoer ... 'foutmelding - waarschijnlijk is er een fout in uw SQL-statement. Soms komt het door dbDelta ()
de strengheid. Als je toevoegt wp_die ();
na dbDelta ()
, hierdoor wordt de verwerking gedood en (met 'WP_DEBUG' ingesteld op true) worden eventuele foutberichten weergegeven.
In dit artikel hebben we gekeken naar redenen waarom u aangepaste tabellen niet zou moeten en moeten gebruiken, maar ook de details die u moet overwegen en tot slot hoe u een tabel kunt maken. Het volgende deel van deze serie gaat over saniteren, kijken naar SQL-injectie en hoe je jezelf ertegen kunt beschermen. De code in dit artikel is beschikbaar in deze GitHub-repository en wordt bijgewerkt naarmate de reeks verdergaat.
$ wpdb
klasse