Wenn 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
ID | name | sportart | gruendungsjahr |
---|---|---|---|
1 | SSV Jahn Regensburg | Fußball | 1889 |
2 | FC Bayern München | Fußball | 1900 |
3 | Stuttgarter Kickers | Fußball | 1899 |
4 | Dallas Mavericks | Basketball | 1967 |
5 | Denver Broncos | Football | 1960 |
6 | Pittsburgh Steelers | Football | 1933 |
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.
Du kommst bei deinem Projekt nicht weiter oder brauchst einen Boost? Dann lass dir von mir helfen zum Beispiel bei: ► Beratung für Selbständige, Gründer & Ideenschmiede Egal, ob du erste Tipps brauchst. Einmal über deine Idee reden möchtest oder mit mir das Konzept für das nächste Facebook ausarbeiten willst. ► Entwicklung von Software, APPs & Webseiten Beispielsweise: WordPress Shops & Plugins, (Gaming-)Apps, Datenbank-Applikationen oder andere smoothe Anwendungen! Mehr Infos, Preise und Kontaktmöglichkeiten findest du hier! |
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
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 :-/
Hallo und Guten Morgen,
ich habe das selbe Thema. Der gleiche Code in drei unterschiedlichen Installationen (Themes) ergibt zweimal die richtige Ausgabe und einmal erscheint die Ausgabe direkt im Contentbereich und zusätzlich direkt unter dem -Tag, also doppelt.
> Das liegt vermutlich daran, dass du es tatsächlich auch dort ausgibst.
Nein, die Ausgabe ist da nicht vorgesehen und wird auch nur einmal eingebaut.
Ich habe schon Stunden damit verbracht zu suchen, warum der Code unter BODY interpretiert wird. Es ist auch kein Unterschied, ob man das mit Shortcode oder innerhalb eines Plugins bewältigt.
Grüße
Heinz
Hmm, schwierig zu sagen. Hab ich so noch nicht gesehen. Vielleicht irgend eine Theme-Besonderheit mit einem selbstgebautem Caching?
Tolle Seite und nützliche Informationen!
Besten Dank!
lg, Markus
nach lagem Suchen endlich mal eine Seite gefunden, die auf deutsch und verständlich Grundlegendes erläutert, danke
Tolle Seite, Danke für den einfachen Einstieg.
Zu meiner Verteidigung, bin totaler PHP Neuling…
Was ich nicht verstanden habe: Ein einzelnes Resultat kann ich ja gut mit der Shortcode Funktion mittels meinem Plugin zurückbringen. Was mache ich aber bei mehreren Ergebnissen aus der DB Abfrage? Wie/wo kann ich diesen Code in meinem Plugin aufrufen und zur Anzeige bringen?
Habe schon Stunden verplempert, kriege die Ausgabe aber nicht in eine Seite rein. 🙂
Liebe Grüsse, Reto
Hi Reto,
du musst die Daten eben mit einer foreach Schleife oder einer for-Schleife durchlaufen und ausgeben. Wie im letzten Code-Beispiel angegeben.
Hi Robert,
Danke für die prompte Antwort.
Ja Schlaufe ist klar, aber in deinem letzten Beispiel lieferst du die Ausgabe per echo Befehl. Dazu müsste ich die Funktion ja direkt aus einer WP Seite heraus aufrufen können, richtig? Das scheint WordPress zu verhindern oder ich habe zumindest noch nicht herausgefunden wie das geht…
Deshalb habe ich mich gefragt, ob man die Ausgabe in einen Array verpacken könnte und dann zum Anzeigen der Shortcode Funktion übergeben kann, ginge das?
Viele Grüsse, Reto
Ach, muss ich noch ändern. Ab einer bestimmten WordPress Version geht das mit echo glaub ich nicht mehr.
Da musst den String in einer Variable speichern und als return Wert zurückgeben, damit es als Plugin funktioniert.
Ich hoffe, das hilft dir weiter.
Ich hab jetzt eine Tabelle angelegt und würde gerne nur den Inhalt aus einer Zelle in einem WordPress-Beitrag bzw. Seite wiedergeben. Wie kann ich das machen?