Wie implementiere ich ein WordPress-Plugin-Update, das die Datenbank ändert?

10

Ich entwickle ein WordPress-Plugin, das mehrere eigene Datenbanktabellen hat. Das Plugin erstellt diese Tabellen bei Aktivierung und entfernt sie beim Löschen / Deinstallieren.

Ich muss einen Aktualisierungsprozess des Plugins implementieren, der den Code des Plugins sowie die Tabellenstruktur aktualisiert. Der einfachste Fall wäre, einer der Tabellen eine neue Spalte hinzuzufügen. Der komplexere Fall wäre, eine neue Tabellenstruktur zu erstellen und den Inhalt entsprechend zu aktualisieren.

Wie würden Sie empfehlen, dieses Problem zu lösen? Gibt es integrierte WordPress-Funktionen, die helfen können?

Mischa Moroshko
quelle

Antworten:

4

Der richtige Weg, dies heutzutage zu tun, besteht darin, Ihr Schema als Datei in die Plugin-Quelle aufzunehmen und die eingebaute WordPress-Funktion dbDelta () zu verwenden, um die Datenbank nach Bedarf mithilfe dieses Schemas zu aktualisieren. Der tatsächlich erforderliche Code ist sehr einfach:

$sql = file_get_contents( plugin_dir_path(__FILE__) . "/schema.sql" );
dbDelta( $sql );

Dadurch wird die Datenbank nach Bedarf für Sie erstellt und aktualisiert. Bei der letzten Überprüfung wurden keine alten nicht verwendeten Spalten gelöscht, sodass Sie dies über eine Versionsprüfung codieren müssen. Dies ist eine schöne Funktion von WordPress und eine enorme Zeitersparnis. Beachten Sie beim Erstellen der Datei schema.sql, dass Sie den Abstand in einen MySQL-Schemaexport genau so kopieren, wie der Code dbDelta () angeblich sehr pingelig in Bezug auf den Abstand ist. Sie sollten auch die Version der Datenbank testen. Wenn dies nicht die neueste ist, rufen Sie die oben genannte Version auf, um die Datenbank zu aktualisieren. Möglicherweise müssen Sie auch bestimmte Aktualisierungen vornehmen, um Änderungen abzudecken, die bei dbDelta () nicht richtig sind (z. B. Löschen einer Spalte). Es ist einfach, einen einfachen logischen if-Test zu schreiben, um festzustellen, ob die Version aktualisiert wurde, und diese manuellen Updates über $ wpdb durchzuführen. Beispielsweise können Sie eine Spalte löschen, die jetzt nicht mehr verwendet wird.

$installed_ver = get_option(MY_DB_VERSION);
$wpp = $wpdb->prefix . "mypluginname";
if ($installed_ver < 102)
        $wpdb->query("ALTER TABLE ${wpp}_movies DROP nft_date");
if ($installed_ver < 107)
        $wpdb->query("ALTER TABLE ${wpp}_movies CHANGE lastupdated "
        . "lastupdated TIMESTAMP on update CURRENT_TIMESTAMP "
        . "NOT NULL DEFAULT CURRENT_TIMESTAMP");

update_option(MY_DB_VERSION, $db_version);

Dies wird durch das Ausführen von Code vereinfacht. Ich entschuldige mich, wenn ich ihn bei der Vereinfachung für die Veröffentlichung beschädigt habe.

Beachten Sie auch, dass WordPress ab WordPress 3.9.2 beim Aktualisieren des Plugins nicht immer den Aktivierungs-Hook ausführt (insbesondere, wenn ein Massenupdate über die Seite Dashboard-Updates durchgeführt wird).

Brian C.
quelle
In diesen Tagen habe ich begonnen, die Version der Datenbank aus der Mod-Zeit der Datei schema.sql zu übernehmen. Dies bedeutet, dass nur das Aktualisieren der Datei register.sql ausreicht, um ein Datenbank-Upgrade durchzuführen. Sie müssen nicht daran denken, die Datenbankversion zu bearbeiten. So etwas wie: $ db_version = filemtime ("schema.sql");
Brian C
1
Wenn sich also die Dateizeit von einem externen Element wie dem Verschieben von Servern ändert, ändern sich die mtime- und die db-Version?
Walf
Die Dateizeit ist immer in GMT angegeben, und die Server unterscheiden sich selten um einige Sekunden. Daher ist es fast unmöglich, dass sie dadurch zweimal ausgelöst werden. Selbst wenn es erneut ausgelöst wird, wird kein Schaden angerichtet, da es einmal ausgeführt wird und einen Vergleich mit der Live-Datenbank durchführt, offensichtlich ohne etwas zu ändern. Das ist das Schöne an dbDelta () - es kann problemlos mehrere Male ausgeführt werden. Gute Frage, danke.
Brian C
3

Kurz gesagt, ja die - $wpdbKlasse. Weitere Informationen finden Sie im Codex .

Wann immer Sie mit einer benutzerdefinierten Tabelle (oder wirklich einer beliebigen Tabelle) interagieren, sollten Sie diese durchgehen. $wpdbStellen Sie insbesondere sicher, dass Sie mit der prepareMethode vertraut sind, mit der Abfragen vermieden und Injektionen verhindert werden können.

Sie sollten bereits damit vertraut sein, da Sie es zum Erstellen der Tabelle verwenden sollten. An Ihrem Installations-Hook sollten Sie Folgendes haben:

$charset_collate = '';
if ( ! empty($wpdb->charset) )
    $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";
if ( ! empty($wpdb->collate) )
    $charset_collate .= " COLLATE $wpdb->collate";

//Create custom table
$sql_custom_table ="CREATE TABLE {$wpdb->prefix}my_table (
    id bigint(20) unsigned NOT NULL auto_increment,
    column_a varchar(255) default NULL,
    column_b varchar(255) default NULL,
    PRIMARY KEY  (id)
    ) $charset_collate; ";

require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql_custom_table);

Dieser Code wird tatsächlich ausgeführt, wenn das Plug-In aktiviert ist (dh nicht nur installiert ist). Es wird also ausgeführt, wenn jemand das Plug-In automatisch aktualisiert . Hinweis: Wenn das Upgrade durch manuelles Ersetzen des Plug-Ins erfolgt, wird dies nicht der Fall sein. Daher müssen Sie den obigen Code admin_initbeim Upgrade Ihres Plug-Ins auslösen (Versionsnummer in der Optionstabelle speichern, mit der aktuellen Version vergleichen). .

Jetzt möchten Sie normalerweise nicht, dass der CREATE TABLESQL-Befehl jedes Mal ausgeführt wird, wenn Sie das Plug-In aktualisieren - hier dBDelta()kommt es ins Spiel .

Bevor Sie den obigen Befehl ausführen, wird überprüft, ob die Tabelle vorhanden ist. Außerdem werden die Spaltentypen überprüft. Wenn die Tabelle nicht vorhanden ist, wird sie erstellt, wenn dies der Fall ist. Einige Spaltentypen haben sie jedoch geändert. Wenn eine Spalte nicht vorhanden ist, wird sie hinzugefügt.

Leider - wenn Sie eine Spalte aus dem oben genannten entfernen, wird die Spalte nicht automatisch entfernt. Um Spalten / Tabellen zu entfernen, müssen Sie diese speziell DROPfestlegen (überprüfen, ob sie vorhanden sind, bevor Sie dies tun).

Stephen Harris
quelle