Aangepaste databasetabellen de database onderhouden

Gedurende de levensduur van uw aangepaste tabel zult u waarschijnlijk merken dat u wijzigingen moet aanbrengen in wat het opslaat, of hoe het wordt opgeslagen. Dit kan het gevolg zijn van een behoefte om meer (of minder) gegevens op te slaan. Het kan zijn dat het oorspronkelijke ontwerp van uw database niet bedoeld was om (efficiënt) om te gaan met wat uw gebruikersbestand nu eist. Hoe dan ook, we moeten weten hoe we onze tafel kunnen aanpassen aan onze nieuwe behoeften. Dit is waar we in deze tutorial naar zullen kijken, en we zullen ons vooral op de functie concentreren dbDelta () die we voor het eerst hebben ontmoet in deel een.


dbDeta

Gelukkig wordt het grootste deel van het legwerk in het omgaan met databasewijzigingen gedaan door de WordPress-functie dbDelta (). We hebben deze functie in deel een gebruikt om onze tabel te maken, maar het doet eigenlijk veel meer dan dat: voorafgaand aan het uitvoeren van de query die we hebben gegeven, wordt gecontroleerd of de tabel al bestaat. Zo niet, dan wordt de tabel gemaakt, maar als deze bestaat, vergelijkt deze het verschil (vandaar de naam) en maakt sommige veranderingen. Daarom hebben we in deel één niet handmatig gecontroleerd of de tabel al bestond.

Als de tabel al bestaat, maar verschilt van de tabel die door de SQL wordt gegeven (bijvoorbeeld de bestaande tabel heeft een ontbrekende kolom of een andere kolomcollation), dan dbDelta () past deze updates automatisch toe. Op deze manier kunnen we een nieuwe versie van onze plug-in vrijgeven die onze tabel verandert door simpelweg 'dbDelta ()' toe te passen met de gewijzigde SQL. Bijna.

helaas, dbDelta () is niet van toepassing allemaal veranderingen. Laten we eens aannemen dat we in onze nieuwste plug-in-release geen kolom nodig hebben, en we willen deze verwijderen. Dus we verwijderen het uit de SQL-query in deel één en in de upgrade-routine-aanroep wptuts_create_tables (). Na het upgraden zullen we zien dat de kolom er nog steeds is. Erger nog: gebruikers die van de oude naar de nieuwe versie upgraden, hebben dan een structureel andere tabel dan degenen die met de nieuwe versie beginnen..

Notitie: dbDelta () is niet destructief: dit is het zal ontbrekende kolommen toevoegen of veranderde kolommen veranderen, maar het zal geen kolommen of indexen verwijderen.

Dus wat doet het dbDelta () eigenlijk doen?

Laten we onszelf herinneren aan de SQL-query die we doorgeven dbDelta () bij het maken van de tabel:

 $ sql_create_table = "MAAK TAFEL". $ wpdb-> wptuts_activity_log. "(log_id bigint (20) unsigned NOT NULL auto_increment, user_id bigint (20) unsigned NOT NULL standaard '0', activity varchar (20) NOT NULL standaard 'updated', object_id bigint (20) unsigned NOT 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);

Eerst haalt het alle CREËER TAFEL vragen (u kan geef meerdere vragen door aan dbDelta () in één keer, scheidt ze door een ';', maar om de leesbaarheid te verbeteren doe ik het liever niet). Hiervan is de tabelnaam vereist, $ table, en loopt

 $ wpdb-> get_results ("DESCRIBE $ table;");

Hiermee wordt een array met bestaande kolommen geretourneerd. Elke kolom is eigenlijk een object met informatie over die kolom (de naam, het type, de standaardwaarde, enzovoort). Bijvoorbeeld onze log_id kolom ziet eruit als:

 stdClass Object ([Field] => log_id [Type] => bigint (20) unsigned [Null] => NO [Key] => PRI [Default] => [Extra] => auto_increment)

Als de tabel niet bestaat, wordt een lege array geretourneerd en wordt de tabel gemaakt. Anders dbDelta () Vervolgens doorloopt elke regel van de doorgegeven query, extraheert de kolommen en slaat ze op in een array $ cfields. Het doet hetzelfde met elk van de toetsen (inclusief primair).

Vervolgens gaat het door elk van de bestaand kolommen. Als ze aanwezig zijn in de bovenstaande array, $ cfields, ze zijn verwijderd. Het vergelijkt vervolgens hun type, als ze niet overeenkomen, genereert het automatisch een corresponderend ALTER TABLE query die later moet worden uitgevoerd. Nadat dit is gedaan, blijven de enige kolommen over $ cfields zijn degenen die nog niet bestaan. Hieruit genereert het verder ALTER TABLE vragen om deze kolommen te maken.

Vervolgens voert het een bijna identieke procedure uit voor toetsen.


Doe voorzichtig

Het vermogen van dbDelta () om al deze analyses te doen, heeft een hoge prijs: het is een kwestie van wat het zal accepteren (of correct interpreteren). Bijvoorbeeld:

  • Elk deel van de query (bijvoorbeeld elke kolom en sleutelverklaring) moet een eigen regel hebben. Bijvoorbeeld
     user_id bigint (20) niet ondertekend NIET NULL standaard '0', activiteit varchar (20) NOT NULL standaard 'bijgewerkt',

    zal handelen alsof het activiteit kolom is niet aanwezig. Het juiste formaat is:

     user_id bigint (20) niet ondertekend NIET NULL standaard '0', activiteit varchar (20) NOT NULL standaard 'bijgewerkt',
  • U moet KEY gebruiken in plaats van het synoniem INDEX.
  • Alle KEY's moeten een naam krijgen. Schrijf bijvoorbeeld niet
    KEY (user_id)]

    in plaats daarvan zou het moeten zijn

    KEY user_id (user_id)

    (hoewel de naam niet hetzelfde hoeft te zijn als de kolom).

  • De PRIMAIRE SLEUTEL moet geen naam krijgen, maar eerder wel twee ruimtes tussen HOOFDSLEUTEL en de kolomverklaring: (Log_id). Bijvoorbeeld,
     PRIMAIRE SLEUTEL (log_id),

    zal een fout veroorzaken. Het juiste formaat is:

     PRIMAIRE SLEUTEL (log_id),

Dit is geen volledige lijst. Als algemene regel moet u extra spaties rond en tussen zoekwoorden vermijden, zoals CREATE en TAFEL en er zouden geen extra spaties rond kolommen moeten zijn. De binnenkant van dbDelta () vertrouw op gebruik preg_match () om informatie uit de doorgegeven SQL-instructie te extraheren - en als zodanig kan het vrij gemakkelijk fout gaan als die verklaring niet op de juiste manier is opgemaakt.

Sommige van deze fouten zullen in stilte voorkomen (bijvoorbeeld als u geen a geeft SLEUTEL een naam, dbDelta () zal het blijven dupliceren). Om deze reden is het belangrijk dat u uw tabel handmatig controleert (met phpMyAdmin of vergelijkbaar) om te controleren of uw code correct werkt.


Kolommen toevoegen of wijzigen

Met dbDelta (), dit is echt eenvoudig - laten we veronderstellen dat we het willen maken object_id een index, voeg een extra kolom toe user_ip om het IP-adres van de gebruiker op te slaan en het type van de activiteitskolom in te wijzigen VARCHAR (30), we vervangen eenvoudig de oorspronkelijke SQL-query met:

 $ sql_create_table = "MAAK TAFEL". $ wpdb-> wptuts_activity_log. "(log_id bigint (20) unsigned NOT NULL auto_increment, user_id bigint (20) unsigned NOT NULL standaard '0', user_ip varchar (15), activity varchar (30) 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), KEY object_id (object_id),) $ charset_collate; ";

Dan zorgen we ervoor dat we bellen wptuts_create_tables () in de upgrade-routine en de wijzigingen worden van kracht.


Kolommen verwijderen

Sinds dbDelta () zal geen kolommen verwijderen, alleen het verwijderen van de juiste regel uit de zoekopdracht is niet voldoende (het is echter nog steeds noodzakelijk). In plaats daarvan moeten we dingen handmatig doen.

Til eerst een array bestaande kolommen uit:

 $ existing_columns = $ wpdb-> get_col ("DESC $ wpdb-> wptuts_activity_log", 0);

Als de kolommen die we willen verwijderen, aanwezig zijn, kunnen we deze verwijderen met een ALTER TABLE query:

 $ remove_columns = array ('object_id'); // Array van kolommen om $ remove_columns = array_intersect ($ remove_columns, $ existing_columns) te verwijderen; if (! empty ($ remove_columns)) $ wpdb-> query ("ALTER TABLE $ wpdb-> wptuts_activity_log DROP COLUMN" .implode (', DROP COLUMN', $ remove_columns). ';');

Sleutels verwijderen

Net als bij kolommen, krijg je eerst een reeks indexen:

 $ existing_keys = $ wpdb-> get_col ("SHOW INDEX VANAF $ wpdb-> wptuts_activity_log WHERE Key_name! = 'PRIMARY';", 2);

Als de sleutels die we willen verwijderen dan bestaan, kunnen we ze verwijderen zoals hierboven, maar nu gebruiken DROP INDEX

 $ remove_keys = array ('user_id'); // Serie van sleutels om $ remove_keys = array_intersect ($ remove_keys, $ existing_keys) te verwijderen; if (! empty ($ remove_keys)) $ wpdb-> query ("ALTER TABLE $ wpdb-> wptuts_activity_log DROP INDEX" .implode (', DROP INDEX', $ remove_keys). ';');

Upgrade Routine

Nu we weten hoe onze database te upgraden - laten we kijken hoe we dit in onze plug-in moeten doen. We slaan al onze upgradeafhandeling op in de functie: wptuts_activity_log_upgradecheck (). Merk op dat de plug-in activeringshaak dat wel zal doen niet wordt geactiveerd bij het bijwerken van een plug-in: om ervoor te zorgen dat onze upgrade-routine zijn werk doet, houden we ons aan admin_init.

Om te controleren welke upgrade-routines we moeten uitvoeren, bewaren we de plug-inversie in de database. We vergelijken deze versie (de geïnstalleerde versie) met de huidige (geactiveerde) versie van de plug-in:

  • Als er geen versie in de database staat, is deze een nieuwe installatie en voegen we gewoon de huidige versie toe
  • Als er is een versie in de database, en het is de huidige versie, we doen niets
  • Anders is het een oudere versie, dus we zullen alle noodzakelijke upgrade-routines doorlopen.
 add_action ('admin_init', 'wptuts_activity_log_upgradecheck'); function wptuts_activity_log_upgradecheck () // Versie van huidig ​​geactiveerde plugin $ current_version = '1.3'; // Database-versie - dit kan een upgrade nodig hebben. $ installed_version = get_option ('wptuts_activity_log_version'); if (! $ installed_version) // Geen geïnstalleerde versie - we nemen aan dat het pas net is geïnstalleerd add_option ('wptuts_activity_log_version', $ current_version);  elseif ($ installed_version! = $ current_version) / * * Als dit een oude versie is, voer dan enkele updates uit. * / // Geïnstalleerde versie is vóór 1.1 - upgrade naar 1.1 if (version_compare ('1.1', $ installed_version)) // Code om te upgraden naar versie 1.1 // Geïnstalleerde versie is vóór 1.3 - upgrade naar 1.3 if (version_compare ( '1.3', $ installed_version)) // Code om te upgraden naar versie 1.3 // Database is nu up-to-date: update geïnstalleerde versie naar laatste versie update_option ('wptuts_activity_log_version', $ current_version); 

Notitie: Het is belangrijk dat deze upgrade-routine aanwezig is in de eerste release omdat het de eerste versie (1.0) aan de database zal toevoegen. Als u dit niet doet, kan dit problemen veroorzaken voor degenen die upgraden van 1.0 naar 1.1.

Elk van de afzonderlijke upgrade-routines moet ervoor zorgen dat de database 'up-to-date' is door gebruik te maken van de code die in de eerdere secties is besproken. Belangrijk is dat als we wijzigingen aanbrengen in de CREATE TABLE SQL, u eraan moet denken om die query door te voeren dbDelta () (in ons voorbeeld door te bellen wptuts_create_tables () als onderdeel van de upgrade-routine) om de wijzigingen door te voeren.

Wees voorzichtig met hoe u met updates omgaat tijdens het gebruik dbDelta. Houd er rekening mee dat sommige gebruikers een upgrade uitvoeren voor twee of meer updates. Dus als dergelijke veranderingen niet parallel kunnen worden doorgevoerd, dan moet je verschillende stappen upgraden, waarbij je 'dbDelta ()' meerdere keren oproept, en de juiste wijzigingen voor die fase aanbrengt.


Verwijder Routine

Terwijl we bezig zijn, laten we eens kijken naar opschonen na ons wanneer de plug-in is verwijderd. Dit zijn over het algemeen heel eenvoudige routines: verwijder gewoon de databasetabel, alle opgeslagen opties en eventuele cron-taken die uw plug-in mogelijk heeft geactiveerd. We haken onze routine op de haak voor het verwijderen met behulp van register verwijderen hook ()

 registreren verwijderen haak (__ FILE __, 'wptuts_uninstall_plugin'); function wptuts_uninstall_plugin () global $ wpdb; // Verwijder onze tabel (indien aanwezig) $ wpdb-> query ("DROP TABLE IF EXISTS $ wpdb-> wptuts_activity_log"); // Verwijder de databaseversie delete_option ('wptuts_activity_log_version'); / * Verwijder alle andere opties die uw invoegtoepassing heeft geïnstalleerd en verwijder eventuele cron-taken in de invoegtoepassing * /