Ich habe folgenden Code zum Erstellen einer Tabelle:
$sql = "CREATE TABLE " . $table_name . "("
. "id mediumint(9) NOT NULL AUTO_INCREMENT, "
. "product_id mediumint(9) DEFAULT 0 NOT NULL,"
. "name_type mediumint(9) NOT NULL, "
. "name_key varchar(48) NOT NULL, "
. "valid_until datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, "
. "created_at datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, "
. "updated_at datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, "
. "UNIQUE KEY id (id)"
. ")" . $charset_collate. ";";
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
dbDelta( $sql );
Es funktioniert und die Tabelle wurde erstellt.
Jetzt muss ich die Tabelle aktualisieren und eine neue Spalte hinzufügen (sites_list):
$sql = "CREATE TABLE " . $table_name . "("
. "id mediumint(9) NOT NULL AUTO_INCREMENT, "
. "product_id mediumint(9) DEFAULT 0 NOT NULL,"
. "name_type mediumint(9) NOT NULL, "
. "name_key varchar(48) NOT NULL, "
. "sites_list longtext, "
. "valid_until datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, "
. "created_at datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, "
. "updated_at datetime DEFAULT '0000-00-00 00:00:00' NOT NULL, "
. "UNIQUE KEY id (id)"
. ")" . $charset_collate. ";";
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
dbDelta( $sql );
Aber das funktioniert nicht.
Und ich habe einen Fehler:
WordPress database error: [Table 'table_name' already exists]
Was ist falsch?
Danke.
Der Code selbst der dbDelta-Funktion ist sehr komplex. Aber durch Versuch und Irrtum sind mir einige Verhaltensweisen der dbDelta-Funktion aufgefallen aktualisieren Verhalten:
- Die Primärschlüsselspalte wird nicht umbenannt
- Es wird keine Spalte entfernt
- Wenn Sie versuchen, eine alte Spalte umzubenennen, wird lediglich eine neue Spalte erstellt und die alte beibehalten.
Lange Erklärung
dbDelta ist eine Funktion, die man normalerweise nutzen soll register_activation_hook
, aber dies wird nicht bei Plugin-Updates ausgelöst, sodass keine Tabellen für Ihre Benutzer erstellt werden, die eine bestehende Installation aktualisieren. Um dbDelta-Updates zum Laufen zu bringen, müssen Sie es also zunächst einbinden admin_init
.
Allerdings handelt es sich hierbei um eine ziemlich umfangreiche Funktion, sodass sie nur bei Bedarf ausgeführt werden darf. Dafür können Sie eine behalten my_plugin_db_version
Option in der Datenbank und prüfen Sie damit, ob Sie dbDelta ausführen sollten oder nicht.
Wenn bereits eine automatisch geladene Option geladen wird, ist es sogar noch besser, diese zu verwenden, da die Prüfung keine Auswirkungen auf die Leistung hat, da automatisch geladene Optionen zu Beginn des WordPress-Lebenszyklus in den Speicher geladen werden.
Dies kann im Code ausgedrückt werden als:
add_action('admin_init', 'my_plugin_maybe_run_delta');
function my_plugin_maybe_run_delta() {
// Here we are not using an existing autoloaded option to keep the example short
$dbVersion = get_option('my_plugin_db_version');
// Early bail: No need to run dbDelta
if ($dbVersion === '1.0.0') {
return;
}
// dbDelta here...
// Now set the db version so it can early bail next time...
update_option('my_plugin_db_version', '1.0.0', false);
}
Nehmen wir nun an, dass ich dieses dbDelta in Version 1.0 meines Plugins habe:
global $wpdb;
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
$tableName = $wpdb->prefix . 'foo';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE $tableName (
id bigint(20) NOT NULL AUTO_INCREMENT,
event longtext NOT NULL,
PRIMARY KEY (id)
) $charset_collate;";
dbDelta($sql);
// Some error happened during dbDelta.
if (!empty($lastErrorBefore) && $lastErrorBefore !== $wpdb->last_error) {
// handle error
}
Dies erzeugt die folgende DDL in der Datenbank:
CREATE TABLE `wp_foo` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`event` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
Jetzt entscheide ich mich für eine Umbenennung id
Zu event_id
also ändere ich das dbDelta und veröffentliche die Version 1.1 des Plugins:
$sql = "CREATE TABLE $tableName (
event_id bigint(20) NOT NULL AUTO_INCREMENT,
event longtext NOT NULL,
PRIMARY KEY (event_id)
) $charset_collate;";
Dieses Delta ändert die Datenbankstruktur für Benutzer, die das Plugin aktualisieren, nicht, sie haben den Primärschlüssel als id
während Neuinstallationen den Primärschlüssel als haben event_id
:
CREATE TABLE `wp_foo` (
`event_id` bigint(20) NOT NULL AUTO_INCREMENT,
`event` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`event_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
Regel Nr. 1 von dbDelta: Die Primärschlüsselspalte wird nicht umbenannt.
Jetzt, in Version 1.2, möchte ich umbenennen event
Zu events
also ändere ich das dbDelta wie folgt:
$sql = "CREATE TABLE $tableName (
event_id bigint(20) NOT NULL AUTO_INCREMENT,
events longtext NOT NULL,
PRIMARY KEY (event_id)
) $charset_collate;";
Dies führt für Benutzer, die ein Upgrade von 1.1 auf 1.2 durchführen, zu folgendem Ergebnis:
CREATE TABLE `wp_foo` (
`event_id` bigint(20) NOT NULL AUTO_INCREMENT,
`event` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
`events` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`event_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
Bei Neuinstallationen wird das folgende Ergebnis angezeigt:
CREATE TABLE `wp_wpstg_analytics` (
`event_id` bigint(20) NOT NULL AUTO_INCREMENT,
`events` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`event_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
Dabei wird für Benutzer, die das Plugin seit 1.0 verwenden, das folgende Ergebnis erzielt:
CREATE TABLE `wp_wpstg_analytics` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`event` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
`events` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
Das ist ein ziemlich vernünftiges Verhalten, wenn man darüber nachdenkt. Wenn Sie die Spalte umbenennen event
Zu events
können Sie die Daten für frühere Installationen weiterhin von der alten Spalte in die neue migrieren. Denken Sie daran, die Spalte, die als Primärschlüssel zugewiesen ist, niemals umzubenennen.
Der Fehler ist ziemlich klar. Sie können die Tabelle nicht erstellen, da sie bereits vorhanden ist. Du willst wahrscheinlich
ALTER TABLE
oderCREATE TABLE IF NOT EXISTS
– naththedeveloper
22. März 2016 um 16:08
Ja, das wird großartig, aber aus dem Codex: Die dbDelta-Funktion untersucht die aktuelle Tabellenstruktur, vergleicht sie mit der gewünschten Tabellenstruktur und fügt die Tabelle nach Bedarf hinzu oder ändert sie, sodass sie bei Aktualisierungen sehr praktisch sein kann. https://stackoverflow.com/questions/36159055/table-not-updating-with-wordpress-dbdeltacodex.wordpress.org/… Ich denke, die Verwendung dbdelta korrekter ist es, das Plugin zu aktualisieren
– Eugen
22. März 2016 um 16:28
Dieses Problem liegt wahrscheinlich daran, dass sich Ihre Felder nicht tatsächlich in separaten Zeilen befinden (dies ist eine der „Bedingungen“, die von der Funktion festgelegt werden). Der Grund dafür ist, dass Sie die Zeichenfolge verketten und dies tatsächlich zu einer einzelnen Zeile führt. I Ich werde eine Antwort hinzufügen und versuchen, dies etwas besser zu erklären.
– naththedeveloper
23. März 2016 um 7:48
Ich versuche, die Verkettung zu entfernen, aber es hat sich nichts geändert. Fehler ist derselbe.
– Eugen
25. März 2016 um 5:34