Mit wpdb Daten aus der WordPress-Datenbank lesen (SELECT)

By | 9. Juni 2016

wordpress wpdb SELECTWenn man eigene Plugins in WordPress erstellen möchte, ist die Funktion, bzw. Klasse wpdb überlebenswichtig. Mit dieser könnt ihr mit eurer Datenbank kommunizieren und genau das machen, was benötigt wird. Das heißt ihr könnt Daten eintragen (Insert), updaten (Update), abrufen (Select) und noch viel mehr.

Natürlich könnt ihr auch einfach die WordPress-Dokumentation lesen, die im Falle des wpdb-Objekts ziemlich gut ist. Aber ich denke ich kann noch ein paar Beispiele beisteuern, die den ein oder anderen Denkfehler verhindert. Diese haben mir extrem viel Zeit gekostet.

In diesem Blogbeitrag konzentriere ich mich jedoch vor allem auf das Abfragen von Daten.

Wieso wpdb?

Programmierer, die zum ersten Mal ein WordPress-Plugin programmieren, werden sich wohl fragen, wieso man dafür überhaupt eine eigene Funktion benötigt. Schließlich gibt es in PHP schon eine eigene Klasse dafür.

wpdb liefert allerdings noch die ein oder andere nützliche Funktion mit, die ihr in eurem Plugin gebrauchen könnt. Außerdem kümmert sie sich um die Verbindung zur Datenbank. Das heißt, wenn ihr beispielsweise eure WordPress Seite umzieht, dann müsst ihr nur die wp_config.php Datei anpassen, aber nicht euren Code. Und Wartungseffizienz sollte das Ziel jedes Programmierers sein.

Grundeinstellung und Beispielszenario

Zuallererst dürft ihr nie vergessen, die Klasse zu initialisieren. Das geschieht mit der globalen Variable $wpdb:

function test()
{
  global $wpdb; //Wenn du in dieser Funktion mit deiner Datenbank kommunizieren möchtest, musst du die globale Klasse wpdb initialisieren. 
}

Um meine Beispiele anschaulicher zu gestalten werde ich mich von folgender „Datenbanktabelle“ bedienen.

wp_mannschaften

IDnamesportartgruendungsjahr
1SSV Jahn RegensburgFußball1889
2FC Bayern MünchenFußball1900
3Stuttgarter KickersFußball1899
4Dallas MavericksBasketball1967
5Denver BroncosFootball1960
6Pittsburgh SteelersFootball1933

Abfragen mit wpdb

Es gibt mehrere Möglichkeiten, Abfragen mit wpdb durchzuführen. Ich werde lediglich auf die Möglichkeit einen, bzw. mehrere Datensätze abzufragen eingehen. Es ist mit „get_var“ zwar noch möglich eine einzelne Variable abzufragen, allerdings habe ich das noch nie gebraucht, sehe auch keine große Notwendigkeit dafür.

SELECT ROW mit $wpdb->get_row

Mit $wpdb->get_row(„Abfragestring“) könnt ihr eine einzelne Zeile abrufen. Gibt es mehrere Ergebnisse zu eurem SQL-Befehl, spuckt die Funktion den ersten Eintrag, den eure Datenbank findet aus.

Möchte ich also alle Informationen zum SSV Jahn Regensburg haben, sieht meine Abfrage folgendermaßen aus:

function get_infos()
{
  global $wpdb;
 
  $mannschaftsinfos = $wpdb->get_row("SELECT * FROM ".$wpdb->prefix."mannschaften WHERE ID = 1"); 
 
  echo "Vereinsname: ".$mannschaftsinfos->name; //SSV Jahn Regensburg  
}

Die Informationen sind also in einem Objekt gespeichert. Die Klasse erlaubt auch noch eine Ausgabe als assoziatives und numerisches Array. Aber da ich bisher keine Anwendungsfälle dafür gefunden habe, lasse ich das einfachheitshalber weg.

$wpdb->prefix

Für alle, die sich wundern warum nach dem FROM nicht wp_mannschaften sondern „.$wpdb->prefix.“mannschaften steht, ist hier schon die erste Lektion, die ich nach tausenden Zeilen Code schmerzhaft lernen durfte. Der Präfix einer Datenbanktabelle sollte sich natürlich zufällig zusammensetzen um es beispielsweise Hackern bei einem Angriff auf eure Datenbank schwerer zu machen.

Manchmal haben Präfixe allerdings auch praktischen Wert, wenn du zum Beispiel die gleiche Datenbanktabelle öfters verwenden möchtest. Ein Anwendungsbeispiel ist mein Browsergame. Damit ich einzelne „Welten“ sauber abschließen kann und die Performance erhöhe, hat jede Tabelle die zu einer Welt gehört ihren eigenen Präfix. Die Tabellen heißen dann bspsw.: welt1_mitspieler, welt2_mitspieler, welt3_mitspieler, welt1_clans, welt2_clans, welt3_clans usw…

Zurück zum WordPress Plugin. Ich dachte dummerweise, WordPress Tabellen haben generell den Präfix „wp_“ was freilich nicht stimmt. Jedes WordPress Projekt sollte unbedingt einen zufälligen anderen Tabellenpräfix besitzen. Diesen kann und muss man auch in der „wp_config.php“ Datei konfigurieren. Dort holt sich auch die Klasse wpdb den Präfix.

SELECT RESULTS mit $wpdb->get_results

Mit dem Befehl $wpdb->get_results(„SQL String“); können mehrere Ergebnisse aus der Datenbank ausgelesen werden.

Möchte ich zum Beispiel den Namen und das Gründungsjahr aller Mannschaften, die nach 1901 gegründet worden sind ausgeben lassen, gehe ich folgendermaßen vor:

function get_mannschaften()
{
  global $wpdb;
 
  $mannschaftsinfos = $wpdb->get_results("SELECT name, gruendungsjahr FROM ".$wpdb->prefix."mannschaften WHERE gruendungsjahr > 1901"); 
  $gefundene_mannschaften = $wpdb->num_rows;
  foreach($mannschaftsinfos as $mannschaft)
  {
    echo "Vereinsname: ".$mannschaft->name;
    echo " | Gründungsjahr: ".$mannschaft->gruendungsjahr."<\br>";
  }
  echo "Gefundene Mannschaften: ".$gefundene_mannschaften;
}  
  /*
  Vereinsname: Dallas Mavericks | Gründungsjahr: 1967
  Vereinsname: Denver Broncos | Gründungsjahr: 1960
  Vereinsname: Pittsburgh Steelers| Gründungsjahr: 1933 
  Gefundene Mannschaften: 3
  */

Die foreach Schleife ist nötig, da die Funktion standardmäßig ein Array zurückliefert, in denen die Objekte gespeichert sind. Theoretisch könnte man natürlich auch das Array selbst durchgehen. Möchte man den Vereinsnamen des ersten Eintrags zurückgeben könnte man auch $mannschaftsinfos[0]->name verwenden.

Eine kleine Erleichterung ist auch die Funktion $wpdb->num_rows, welches die Anzahl der Ergebnisse zurückgibt. Diese muss aber unmittelbar nach der Abfrage aufgerufen werden. Sie erweist sich als hilfreich, wenn man doch eine „normale“ FOR-Schleife verwenden möchte.

Select Rückgabewerte

Was mir zu Beginn auch viele Nerven gekostet hat war, dass ich die Rückgabewerte missinterpretiert habe. $wpdb->get_row und $wpdb->get_results liefern folgende Werte zurück (mit obigen Beispiel):

Bei Erfolg: 

  Array ( [0] => stdClass Object ( [name] => Dallas Mavericks  [gruendungsjahr] => 1967 ) 
          [1] => stdClass Object ( [name] => Denver Broncos [gruendungsjahr] => 1960 ) 
          [2] => stdClass Object ( [name] => Pittsburgh Steelers [gruendungsjahr] => 1933 )
        )

Keine Werte gefunden:

  Array ( )

Bei Fehlern:

NULL

In unserem Beispiel möchte man vielleicht wissen, ob es ein Verein gibt, der vor 1800 gegründet wurde:

function get_mannschaften()
{
  global $wpdb;
 
  $mannschaftsinfos = $wpdb->get_results("SELECT name, gruendungsjahr FROM ".$wpdb->prefix."mannschaften WHERE gruendungsjahr < 1800"); 
 
  if($mannschaftsinfos !== NULL) //Wenn nicht Null
  {
    if(!is_empty($mannschaftsinfos)) //Wenn Array nicht leer
    {
      foreach($mannschaftsinfos as $mannschaft) // Gebe Mannschaften aus
      {
        echo "Vereinsname: ".$mannschaft->name;
        echo " | Gründungsjahr: ".$mannschaft->gruendungsjahr."<\br>";
      }
    } else {
      echo "Zu dieser Abfrage wurden keine Ergebnisse gefunden"; //Keine Ergebnisse
    }
  } else {
    echo "Abfragefehler"; //Fehler
  }
}

Dann liefert die Abfrage ein leeres Array zurück, was zur Ausgabe „Zu dieser Abfrage wurden keine Ergebnisse gefunden“ führen würde. Bei kritischen Transaktionen, kann man mit „=== NULL“ auf einen Fehler in der Abfrage prüfen und ein entsprechendes Error Handling einbauen.

Abfragen vor SQL-Injection schützen

Ganz peinlich wird es, wenn dein Plugin durch so etwas simples wie eine SQL-Injection geknackt wird. Also solltest du dir Ärger sparen, indem du deine Abfragen sicher gestaltest. Die WordPress-Dokumentation schlägt unter anderem vor, die Abfragen zuerst zu preparen. Das kann man machen, halte ich persönlich für zu unübersichtlich, weshalb ich die Escape-Funktionen von WordPress nutze, bevor ich eine Variable in einer Abfrage verwende.

Hier ist exemplarisch eine Funktion, die eine Mannschaftsabfrage nach der übergebenen ID ausführen soll. Die Funktion kann von überall aufgerufen werden und womöglich einen Wert aus einer POST oder GET-Variable enthalten. Das wäre ein gefundenes Fressen für Hacker. Deshalb solltet ihr so vorgehen:

function get_infos($mannschaft_id)
{
  global $wpdb;
 
  $mannschaft_id = esc_sql($mannschaft_id); //Escaped den übergebenen Wert
 
  $mannschaftsinfos = $wpdb->get_row("SELECT * FROM ".$wpdb->prefix."mannschaften WHERE ID = '$mannschaft_id'"); 
 
  return $mannschaftsinfos;
}

Die Escape-Funktion gibt es noch für mehrere Anwendungsbeispiele wie die Textarea oder für URLs. Eine Liste und die Erklärungen findet ihr am Ende dieser Doku.

Debugging

Es gibt zwei sehr nützliche Befehle, die einem beim Debuggen bei der Verwendung von wpdb sehr behilflich sind. Dafür muss aber die Variable „Debugging“ in der Datei „wp_config.php“ auf true stehen.

Mein häufigster Fehler, warum meine Abfragen nicht funktionieren sind falsch geschriebene Spaltennamen. Diese kann ganz gut mit dem Befehl

$wpdb->show_errors();

debuggen. Diesen musst du vor der Abfrage ausführen. Show Errors zeigt alle Fehler in der Abfrage an.

Was bei komplexeren Abfragen oft vorkommt ist, dass man einfach einen kompletten Nonsens in seine SQL Anweisung geschrieben hat, die Syntax aber keine Fehler enthält. Man sieht es aber nicht im Code, weil alles durch Variablen und übergebenen Werten unübersichtlich ist. Dann hilft mir immer:

$wpdb->print_error();

weiter. Diesen Befehl musst du allerdings unbedingt direkt nach der Abfrage ausführen. Print Error zeigt die vorherige SQL-Abfrage noch einmal im Klartext an. Egal ob bei Erfolg oder Misserfolg. So kann man relativ schnell sehen, ob man einen Scheiß zusammenprogrammiert hat.

Aber bitte vergesst nicht, die Befehle wieder aus dem Code zu nehmen oder sie zumindest auszukommentieren, wenn ihr fertig mit Debuggen seid.

Ich hoffe, ich konnte euch mit diesem Artikel die SELECT Abfragen mit wpdb ein wenig näherbringen.

Ich würde mich freuen, wenn du meinen Newsletter abonnieren würdest. Dann verpasst du auch keinen interessanten Beitrag mehr.

Benachrichtige mich:



3 thoughts on “Mit wpdb Daten aus der WordPress-Datenbank lesen (SELECT)

  1. Hildebrandt

    Super Anleitung.
    Bin selbst PHP Programmierer und will meine WordPresseite mit Daten aus einer eigenen Dtenbank bestücken und ausgeben.
    Wie bekomme ich es hin, das mir die Daten nicht oberhalb der Design-DIV Kontainer angezeigt werden?
    Kann nix darüber finden. Haben Sie einen Tip bzw. Literatur?
    Viele Grüße

    Reply
    1. Robert Post author

      Das liegt vermutlich daran, dass du es tatsächlich auch dort ausgibst.

      Am Besten ist, du bastelst ein kleines Plugin und machst aus der Ausgabe ein Shortcode. Und diesen Shortcode baust du dann dort ein, wo du möchtest.
      https://codex.wordpress.org/Shortcode_API
      Oder rufst halt die Funktion dort auf, wo es ausgegeben werden soll. Das heißt du suchst den DIV-Container in deinem Design und rufst dort die Funktion auf.

      Wollte dazu auch noch was machen, aber das wird noch dauern, bis ich dazu komme :-/

      Reply

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.