Eigene Tabellen mit dbDelta und $wpdb
Begriffe vorab
- $wpdb: die globale Datenbankklasse von WordPress.
- Tabellenpräfix:
$wpdb->prefix, in der Konfiguration festgelegt (nicht festwp_). - dbDelta: Funktion, die Tabellen anlegt oder an eine neue Definition anpasst.
- Prepared Statement: eine Abfrage mit Platzhaltern, die Werte sicher einsetzt.
Wann eine eigene Tabelle?
Für wenige, einfache Werte genügen Optionen und Post-Meta. Eine eigene Tabelle lohnt, wenn viele Datensätze mit eigenem Aufbau entstehen oder gezielt abgefragt werden: Merklisten vieler Nutzer, Statistikeinträge, Protokolle. Post-Meta bei Millionen Zeilen wird langsam, eine passend indexierte Tabelle nicht.
Tabelle mit dbDelta anlegen
dbDelta() vergleicht die gewünschte Definition mit der vorhandenen und legt an oder ändert. Das macht es wiederholbar – ideal für Updates. Es ist aber pingelig bei der Schreibweise:
- Jedes Feld in einer eigenen Zeile.
- Zwei Leerzeichen zwischen
PRIMARY KEYund der Definition. - Das Wort
KEYstattINDEX. - Keine Apostrophe oder Backticks um Feldnamen.
class MZ_Store {
public static function table() {
global $wpdb;
return $wpdb->prefix . 'mz_items';
}
public static function create_table() {
global $wpdb;
$charset = $wpdb->get_charset_collate();
$sql = "CREATE TABLE " . self::table() . " (
id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
user_id bigint(20) unsigned NOT NULL,
post_id bigint(20) unsigned NOT NULL,
created datetime NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY user_post (user_id,post_id),
KEY post_id (post_id)
) $charset;";
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
dbDelta( $sql );
}
Der eindeutige Schlüssel user_post sorgt dafür, dass derselbe Beitrag pro Nutzer nur einmal gespeichert werden kann – die Datenbank erzwingt, was die Anwendung sonst prüfen müsste.
Sicher lesen und schreiben
public static function add( $user_id, $post_id ) {
global $wpdb;
return $wpdb->insert(
self::table(),
array( 'user_id' => $user_id, 'post_id' => $post_id, 'created' => current_time( 'mysql', true ) ),
array( '%d', '%d', '%s' )
);
}
public static function for_user( $user_id, $limit = 50 ) {
global $wpdb;
return $wpdb->get_results( $wpdb->prepare(
'SELECT post_id, created FROM ' . self::table() . ' WHERE user_id = %d ORDER BY created DESC LIMIT %d',
$user_id, $limit
) );
}
}
Der Tabellenname darf nicht über einen Platzhalter eingesetzt werden, Werte schon. Deshalb kommt der Name aus
$wpdb->prefixund fester Zeichenfolge, alle Nutzerwerte laufen über%d/%s. Eine Verkettung von Nutzereingaben in SQL ist die klassische Einfallstür für SQL-Injection.
Zum Selbermachen
- Lege die Tabelle über die Aktivierung an und prüfe sie in einem Datenbankwerkzeug.
- Füge denselben Eintrag zweimal ein und beobachte, dass der eindeutige Schlüssel den Doppeleintrag verhindert.
- Ergänze eine Spalte, erhöhe die DB-Version und prüfe, dass
dbDeltadie Tabelle anpasst.
Prüfstatus: Belegt (Stand 1. Oktober 2026): Jahreszahlen, Zahlen, Namen und Quellenangaben dieser Lektion, soweit die Quellenliste sie nennt, wurden gegen Primärquellen geprüft. Nicht einzeln belegt: erklärende Darstellung nach Lehrbuchstand und Quellen, die in der Liste als „allgemeine Referenz“ markiert sind. Codebeispiele sind nur auf Syntax geprüft, nicht in WordPress ausgeführt.
Quellen
- WordPress Plugin Handbook – „Creating Tables with Plugins“ (dbDelta-Regeln; developer.wordpress.org/plugins/creating-tables-with-plugins/) (allgemeine Referenz, nicht Zeile für Zeile geprüft)
- WordPress Developer Resources – Klassenreferenz zu wpdb (insert, prepare, get_results, get_charset_collate) (allgemeine Referenz, nicht Zeile für Zeile geprüft)