Wie man in WordPress mit der Datenbank arbeitet
13.Aug.2019 Web-Entwicklung

Wie man in WordPress mit der Datenbank arbeitet

Wer WordPress Plugin­s erstellt oder Themes entwickelt, kommt an manchen Stellen mit den WordPress Standard Funktionen nicht weiter und muss dann selbst mit der Datenbank arbeiten. Wer hier eine eigene Verbindung zur Datenbank mit PHP erstellt, macht sich viel Aufwand der nicht nötig ist, auch in der späteren Pflege. Denn WordPress bringt bereits eine PHP Klasse mit, die so ziemlich jeden Wunsch erfüllt und ziemlich komfortabel ist.

Datenbank Verbindung – ein globales Vergnügen in WordPress

Wer ungefähr so, seine Datenbankverbindung in WordPress erstellt:

$mysqli = new mysqli("localhost", "user", "password", "database");
if ($mysqli->connect_errno) {
    die("Verbindung fehlgeschlagen: " . $mysqli->connect_error);
}

Macht sich ziemlich viel Mühe, die nicht sein muss. Denn eigentlich steht die Datenbank Connection bereits global zur Verfügung und sollte nur noch einmal im Code deklariert werden, was so aussieht:

global $wpdb;

Was ist global $wpdb?

$wpdb ist ein globales Object, welches während des ladens vom WordPress Core durch die Klasse „wpdb“ erstellt wird. Dieses Object enthält z.B. Informationen zu den vorhandenen Tabellen der Datenbank, die letzte durchgeführte Query, die Zugangsdaten, oder auch den verwendeten Tabellen Prefix.

Die wpdb Klasse findest du hier im Core: wp-includes/wp-db.php oder hier auf der  offiziellen Website.

Hier ein Beispiel eines wpdb Objects:

object(wpdb)[3]
  public 'show_errors' => boolean false
  public 'suppress_errors' => boolean false
  public 'last_error' => string '' (length=0)
  public 'num_queries' => int 30
  public 'num_rows' => int 1
  public 'rows_affected' => int 0
  public 'insert_id' => int 0
  public 'last_query' => string 'SELECT COUNT(*) FROM wp_users' (length=29)
  public 'last_result' => 
    array (size=1)
      0 => 
        object(stdClass)[5639]
          public 'COUNT(*)' => string '1' (length=1)
  protected 'result' => 
    object(mysqli_result)[262]
      public 'current_field' => int 0
      public 'field_count' => int 1
      public 'lengths' => null
      public 'num_rows' => int 1
      public 'type' => int 0
  protected 'col_meta' => 
    array (size=0)
      empty
  protected 'table_charset' => 
    array (size=0)
      empty
  protected 'check_current_query' => boolean true
  private 'checking_collation' => boolean false
  protected 'col_info' => null
  public 'queries' => null
  protected 'reconnect_retries' => int 5
  public 'prefix' => string 'wp_' (length=3)
  public 'base_prefix' => string 'wp_' (length=3)
  public 'ready' => boolean true
  public 'blogid' => int 0
  public 'siteid' => int 0
  public 'tables' => 
    array (size=12)
      0 => string 'posts' (length=5)
      1 => string 'comments' (length=8)
      2 => string 'links' (length=5)
      3 => string 'options' (length=7)
      4 => string 'postmeta' (length=8)
      5 => string 'terms' (length=5)
      6 => string 'term_taxonomy' (length=13)
      7 => string 'term_relationships' (length=18)
      8 => string 'termmeta' (length=8)
      9 => string 'commentmeta' (length=11)
      10 => string 'yoast_seo_links' (length=15)
      11 => string 'yoast_seo_meta' (length=14)
  public 'old_tables' => 
    array (size=3)
      0 => string 'categories' (length=10)
      1 => string 'post2cat' (length=8)
      2 => string 'link2cat' (length=8)
  public 'global_tables' => 
    array (size=2)
      0 => string 'users' (length=5)
      1 => string 'usermeta' (length=8)
  public 'ms_global_tables' => 
    array (size=8)
      0 => string 'blogs' (length=5)
      1 => string 'blogmeta' (length=8)
      2 => string 'signups' (length=7)
      3 => string 'site' (length=4)
      4 => string 'sitemeta' (length=8)
      5 => string 'sitecategories' (length=14)
      6 => string 'registration_log' (length=16)
      7 => string 'blog_versions' (length=13)
  public 'comments' => string 'wp_comments' (length=11)
  public 'commentmeta' => string 'wp_commentmeta' (length=14)
  public 'links' => string 'wp_links' (length=8)
  public 'options' => string 'wp_options' (length=10)
  public 'postmeta' => string 'wp_postmeta' (length=11)
  public 'posts' => string 'wp_posts' (length=8)
  public 'terms' => string 'wp_terms' (length=8)
  public 'term_relationships' => string 'wp_term_relationships' (length=21)
  public 'term_taxonomy' => string 'wp_term_taxonomy' (length=16)
  public 'termmeta' => string 'wp_termmeta' (length=11)
  public 'usermeta' => string 'wp_usermeta' (length=11)
  public 'users' => string 'wp_users' (length=8)
  public 'blogs' => null
  public 'blogmeta' => null
  public 'blog_versions' => null
  public 'registration_log' => null
  public 'signups' => null
  public 'site' => null
  public 'sitecategories' => null
  public 'sitemeta' => null
  public 'field_types' => 
    array (size=34)
      'post_author' => string '%d' (length=2)
      'post_parent' => string '%d' (length=2)
      'menu_order' => string '%d' (length=2)
      'term_id' => string '%d' (length=2)
      'term_group' => string '%d' (length=2)
      'term_taxonomy_id' => string '%d' (length=2)
      'parent' => string '%d' (length=2)
      'count' => string '%d' (length=2)
      'object_id' => string '%d' (length=2)
      'term_order' => string '%d' (length=2)
      'ID' => string '%d' (length=2)
      'comment_ID' => string '%d' (length=2)
      'comment_post_ID' => string '%d' (length=2)
      'comment_parent' => string '%d' (length=2)
      'user_id' => string '%d' (length=2)
      'link_id' => string '%d' (length=2)
      'link_owner' => string '%d' (length=2)
      'link_rating' => string '%d' (length=2)
      'option_id' => string '%d' (length=2)
      'blog_id' => string '%d' (length=2)
      'meta_id' => string '%d' (length=2)
      'post_id' => string '%d' (length=2)
      'user_status' => string '%d' (length=2)
      'umeta_id' => string '%d' (length=2)
      'comment_karma' => string '%d' (length=2)
      'comment_count' => string '%d' (length=2)
      'active' => string '%d' (length=2)
      'cat_id' => string '%d' (length=2)
      'deleted' => string '%d' (length=2)
      'lang_id' => string '%d' (length=2)
      'mature' => string '%d' (length=2)
      'public' => string '%d' (length=2)
      'site_id' => string '%d' (length=2)
      'spam' => string '%d' (length=2)
  public 'charset' => string 'utf8mb4' (length=7)
  public 'collate' => string 'utf8mb4_unicode_520_ci' (length=22)
  protected 'dbuser' => string 'einUser' (length=7)
  protected 'dbpassword' => string 'einPasswort' (length=11)
  protected 'dbname' => string 'wordpressDatabase' (length=17)
  protected 'dbhost' => string 'localhost:3306' (length=14)
  protected 'dbh' => 
    object(mysqli)[4]
      public 'affected_rows' => int 1
      public 'client_info' => string 'mysqlnd 5.0.12-dev - 20150407 - $Id: 38fea24f2847fa7519001be390c98ae0acafe387 $' (length=79)
      public 'client_version' => int 50012
      public 'connect_errno' => int 0
      public 'connect_error' => null
      public 'errno' => int 0
      public 'error' => string '' (length=0)
      public 'error_list' => 
        array (size=0)
          empty
      public 'field_count' => int 1
      public 'host_info' => string 'localhost via TCP/IP' (length=20)
      public 'info' => null
      public 'insert_id' => int 0
      public 'server_info' => string '5.7.24-log' (length=10)
      public 'server_version' => int 50724
      public 'stat' => string 'Uptime: 2256  Threads: 1  Questions: 667  Slow queries: 0  Opens: 357  Flush tables: 1  Open tables: 52  Queries per second avg: 0.295' (length=134)
      public 'sqlstate' => string '00000' (length=5)
      public 'protocol_version' => int 10
      public 'thread_id' => int 44
      public 'warning_count' => int 0
  public 'func_call' => string '$db->query("SELECT COUNT(*) FROM wp_users")' (length=43)
  public 'is_mysql' => boolean true
  protected 'incompatible_modes' => 
    array (size=5)
      0 => string 'NO_ZERO_DATE' (length=12)
      1 => string 'ONLY_FULL_GROUP_BY' (length=18)
      2 => string 'STRICT_TRANS_TABLES' (length=19)
      3 => string 'STRICT_ALL_TABLES' (length=17)
      4 => string 'TRADITIONAL' (length=11)
  private 'use_mysqli' => boolean true
  private 'has_connected' => boolean true
  public 'categories' => string 'wp_categories' (length=13)
  public 'post2cat' => string 'wp_post2cat' (length=11)
  public 'link2cat' => string 'wp_link2cat' (length=11)
  public 'yoast_seo_links' => string 'wp_yoast_seo_links' (length=18)
  public 'yoast_seo_meta' => string 'wp_yoast_seo_meta' (length=17)

Methoden zur Datenabfrage

Da uns nun also eine Instanz der wpdb Klasse zur Verfügung steht, können wir diese nutzen und weitere Methoden der Klasse zum Daten abfragen nutzen.

Mehrere Datensätze aus der Datenbank abfragen

Als simples fiktives Beispiel möchte ich einfach alle Benutzer der WordPress Installation aus der Datenbank abfragen. Hierfür nutzen wir die Methode „get_results“ und eine einfache MySQL Query.

global $wpdb;

$users = $wpdb->get_results( 
    'SELECT * FROM ' . $wpdb->users 
);

Wir nutzen also die Methode „get_results“ der initialisierten wpdb Klasse und geben als Parmater eine SQL-Query mit. In der SQL-Query nutzen wir aus unserem Object den bereits definierten Namen der User-Tabelle. Somit müssen wir nicht erst den Prefix der Tabelle abrufen.

Als Ergebnis bekommt man dann ein Array mit allen zutreffenden Rows der Datenbank wieder, welches die Rows als Object beinhaltet. Also z.B. so:

array (size=1)
  0 => 
    object(stdClass)[5735]
      public 'ID' => string '1' (length=1)
      public 'user_login' => string 'admin' (length=5)
      public 'user_pass' => string '$P$BMmZA/g12Lo2Lje37xixCeEmo2bOx3/' (length=34)
      public 'user_nicename' => string 'admin' (length=5)
      public 'user_email' => string 'admin@admin.de' (length=14)
      public 'user_url' => string '' (length=0)
      public 'user_registered' => string '2019-06-28 06:50:07' (length=19)
      public 'user_activation_key' => string '' (length=0)
      public 'user_status' => string '0' (length=1)
      public 'display_name' => string 'admin' (length=5)

Einzelnen Datensatz aus der Datenbank abfragen

Möchte man nur einen bestimmten Datensatz aus der Datenbank abfragen, stellt und WordPress die Methode „get_row()“ zur Verfügung. Die Syntax unterscheidet sich zum vorherigen Beispiel nicht. Der Unterschied macht sich nur am Rückgabewert bemerkbar, denn das ist jetzt kein Array mit Objekten mehr, sondern direkt ein Objekt. Hier ein Beispiel der Abfrage und des Rückgabe-Objektes:

global $wpdb;
$userX = $wpdb->get_row( 
    'SELECT * FROM ' .$wpdb->users . ' WHERE ID = 1'
);

// Rückgabeobjekt
object(stdClass)[5500]
  public 'ID' => string '1' (length=1)
  public 'user_login' => string 'admin' (length=5)
  public 'user_pass' => string '$P$BMmZA/g12Lo2Lje37xixCeEmo2bOx3/' (length=34)
  public 'user_nicename' => string 'admin' (length=5)
  public 'user_email' => string 'admin@admin.de' (length=14)
  public 'user_url' => string '' (length=0)
  public 'user_registered' => string '2019-06-28 06:50:07' (length=19)
  public 'user_activation_key' => string '' (length=0)
  public 'user_status' => string '0' (length=1)
  public 'display_name' => string 'admin' (length=5)

Wir fragen also nur die Row der User ab, wo die ID eins ist und erhalten ein Objekt mit allen Daten der Row.
Die gleichen Daten kannst du auch mit der „get_results()“ Methode erhalten, hast dann aber dein Objekt in einem Array und musst in der späteren Verwendung dieser Daten immer den Index des Arrays mit angeben. Das wäre nicht nur umständlich, sondern macht auch den Code weniger lesbar. Über etwaige Performance Vorteile möchte hier jetzt nicht philosophieren.

Einzelne Value aus der Datenbank abfragen

Nehmen wir einmal an du möchtest lediglich wissen und ausgeben wie viele Benutzer denn in der Datenbank hinterlegt sind, dann kannst du eine weitere Methode Nutzen, um nur diesen einen Wert als Rückgabewert zu erhalten. „get_var()“ gibt dir nur einen Wert zurück, der nicht in einem Array und auch nicht in einem Objekt zurückgegeben wird. Im echten Leben fallen mir hierfür aber nicht sehr viele Einsatzzwecke ein, denn meistens benötigt man auch die Daten und zählt anschließend lieber das Array mit count() oder sizeof().
Hier ein Beispiel einer Abfrage und dem dazugehörigen Rückgabewert als Beispiel:

global $wpdb;
$userCount = $wpdb->get_var(
    'SELECT COUNT(*) FROM ' . $wpdb->users
);

// Rückgabewert
string "1" (length=1)

Tabellen Prefix abrufen

Solltest du dennoch den Prefix abfragen müssen, so kannst du diesen auch aus unserem wpdb Object abfragen. Dies könnte dann in etwa so aussehen:

global $wpdb;
$table = $wpdb->prefix . 'myCustomTable';

Methoden zur Dateneingabe

Selbstverständlich stellt WordPress nicht nur Methoden zum Daten auslesen bereit, sondern auch Methoden mit denen wir Daten in die Datenbank schreiben, oder aktualisieren können. Im Folgenden erkläre ich dir beides anhand eines fiktiven Beispieles.

Neue Daten in die Datenbank schreiben

Für das Schreiben in unsere Datenbank stehen uns wieder mehrere Methoden zur Verfügung. In diesem Beitrag gehe ich aber nur auf die „insert()“ Methode ein, da sie für fast alle Zwecke ausreichen sollte. Ein weiterer Vorteil dieser WordPress Methode ist, dass sie uns das Escapen der Werte abnimmt, denn sie erwartet unescaped Werte.

Die insert() Methode erwartet unescaped Values
Die insert() Methode erwartet unescaped Values

Ein Beispiel mit der Methode „insert()“:

global $wpdb;

$wpdb->insert(
    $wpdb->users,
    array(
       'user_login' => 'mustermann',
       'user_pass'  => 'mustermann123',
       // and so on...
    ),
    array(
        '%s', // %s für String / %d für int
        '%s'
    )
);

Der insert() Methode geben wir drei Parameter mit

  1. Tabellen Name
  2. Ein Array mit den Daten -> Die Keys des Arrays sind die Column Namen
  3. Ein Array mit der Angabe ob unsere Values Strings, oder Integer sind

Daten in der Datenbank aktualisieren

Nicht immer wollen wir neue Daten in die Datenbank schreiben, sondern möchten lieber Daten aktualisieren. Nehmen wir als fiktives Beispiel wieder unseren Admin User, der nun nicht mehr Admin, sondern Admin1 heißen soll (user_nicename) und aktualisieren ihn mit der wpdb Methode „update()“.

$newName = $wpdb->update(
    $wpdb->users,
    array(
        'user_nicename' => 'Admin2'
    ),
    array( 'ID' => 1 ),
    array( '%s' )
);

Bei der Update Methode müssen wir mindestens drei Paramater mitgeben

  1. Tabellenname
  2. Array mit den Daten
  3. und ein Array mit der „WHERE“ Angabe, also wo wir die Daten aktualisieren möchten

Als optionale Parameter können wir ein weiteres Array mit angeben, welches das Format unserer Values bestimmt. Wollen wir die „WHERE“ Klausel dynamisch erstellen, sollten wir für diesen Wert ebenfalls angeben welchen Typen wir erwarten. Dafür geben wir ein weiteres Array mit an. Stimmen dann unsere Values nicht mit der erwarteten Typenangabe überein, wird durch die in der update() Methode aufgerufene Methode „process_fields()“ rejected und die Query abgebrochen.

Andere Datenbanken mit der wpdb Klasse in WordPress nutzen

Hin und wieder kommt es dazu, dass man aus WordPress hinaus auf andere Datenbanken zugreifen muss. Nehmen wir als Beispiel ein bestehendes Tool, welches meinetwegen in Python geschrieben ist und eine reine backend Anwendung ist. Somit wird das Tool durch irgendetwas aufgerufen, speichert die Ergebnisse seiner Funktion in eine Datenbank und wir wollen nun diese Ergebnisse nachträglich auf unserer WordPress Website visualisieren.

Auch hier wäre das erste Beispiel einer Datenbankverbindung dieses Tutorials unpraktisch. Wir wollen den Komfort unserer WPDB Klasse haben und deswegen initialisieren wir diese Klasse einfach neu, mit den neuen Serverdaten.

Das könnte Beispielsweise wie folgt aussehen:

$toolDatabase = new wpdb( 
    'username', 
    'passwort', 
    'datenbank', 
    'serveradresse' 
);

Nun haben wir in unserer Variable $toolDatabase das gleiche Objekt wie in der globalen Variable $wpdb, mit unseren neuen Serverdaten. Anschließend können wir wie vorher auch die Methoden unserer wpdb Klasse auf die Tool Datenbank anwenden. Hier ein kleines Beispiel:

$toolDatabase = new wpdb( 
    'username', 
    'passwort', 
    'datenbank', 
    'serveradresse' 
);

$data = $toolDatabase->get_results( 
    'SELECT * FROM projects'
);

Tobias Keller Web Entwickler
Tobias Keller Web Entwickler

Mit Leib und Seele Web Entwickler, immer auf der Suche nach der nächsten Herrausforderung, offen für Neues, Autodidakt.

Kommentare

Geschlossen wegen DSGVO, Artikel 13 Gedöns