Datenbankabfragen in WordPress mit wpdb

Gerade für Leute die eigene Plugins oder eine eigene einfache Funktion schreiben möchten ist eine Datenbankabfrage in WordPress unabdingbar. Daher behelfen wir uns der Klasse wpdb, die uns WordPress zur Verfügung stellt. Mit dieser kann man beispielsweise Datenbanksätze aktualisieren (Update), neue Datensätze hinzufügen (INSERT) oder einfach nur Daten auslesen (SELECT).

Ich möchte Euch in diesem Blog-Beitrag zeigen, wie Ihr mit dem wpdb-Objekt eine Datenbankabfrage in WordPress macht.

Wie funktioniert die Datenbankabfrage mit wpdb?

Wer sich ein wenig in Programmieren auskennt, der weiß, dass es schon zahlreiche PHP Klassen gibt. Wieso also wpdb? wpdb liefert zusätzlich einige Informationen, die für die Datenbankverbindung hilfreich sein könnten. So müsst Ihr beispielsweise bei einem Umzug eurer Webseite nur die wp-config.php anpassen und nicht den Code.

Beginnen wir mit den wpdb Basics

Wenn Ihr mit der Klasse wpdb arbeiten wollt, dann müsst Ihr sie zunächst einmal initialisieren. Das geschieht mit der globalen Variable $wpdb:

function meinPlugin() {
	global $wpdb;
}

Beispieltabelle wp_posts

Im folgenden Versuche ich euch ein paar Beispiele anhand der folgenden Tabelle zu verdeutlichen.

ID post_title post_category post_status post_type
1 BMW Auto publish post
2 Audi Auto publish post
3 Mercedes Auto publish post
4 Opel Auto publish post
5 Porsche Auto publish post
6 Kawasaki Motorrad publish post
7 Autos Auto publish page
8 Motorräder Motorrad publish page
9 Ruderboot Boote draft page
10 BMW Motorrad publish post

Die Unterschiedlichen Rückgabewerte von wpdb

Ich habe am Anfang selbst einige Zeit benötigt um herauszufinden, welche Abfragen welche Werte zurückgeben. Dabei habe ich für mich festgestellt, dass ich am liebsten mit get_results arbeite, welches mir ein array zurückgibt. Der besseren Übersicht halber hier die möglichen Variablen von wpdb:

Tipp: Variablennamen anklicken und Ihr springt zum entsprechenden Bereich im Beritrag

  • $wpdb->prefix
    $wpdb->prefix gibt den Prefix deiner WordPress Datenbank wieder.
  • $wpdb->get_row
    Mit $wpdb->get_row könnt Ihr eine einzelne Zeile abrufen. Gibt es mehrere Werte wird get_row euch nur den ersten ausgeben.
  • $wpdb->get_results
    Möchtet Ihr mehrere Werte aus der Datenbank von WordPress auslesen, dann solltet Ihr mit $wpdb->get_results arbeiten.
  • $wpdb->num_rows
    num_rows gibt nur die Anzahl der gefundenen Treffer zurück. Muss aber unmittelbar nach dem Abruf der Variable aufgerufen werden.
  • $wpdb->show_errors()
    Zeigt Fehler in der Abfrage an.
  • $wpdb->print_error()
    Zeigt Fehler in der SQL Anweisung an.

Im folgenden möchte ich Euch anhand der möglichen Variablen zeigen, wie Ihr die Daten auf den unterschiedlichen Arten erhaltet und auslesen könnt.

$wpdb->prefix

Bei jeder Installation fragt Euch WordPress welchen Tabellen Prefix Ihr verwenden möchte. Standardmäßig schlägt WordPress „wp_“ vor. Es gibt aber unterschiedliche Gründe diesen zu ändern: Zum einen erschwert man es somit Hackern schnell die Tabellen zu finden. Zum anderen macht es Sinn den Prefix zu ändern, wenn man beispielsweise einen Blog und ein Shopsystem in der selben WordPress Datenbank speichert. Aus der „wp_config.php“ holt sich $wpdb->prefix den Tabellen Prefix. Daher verwende ich anstelle von „wp_posts“ die Variable „.$wpdb->prefix.“posts.

Beispiel $wpdb->prefix: Ändere ich den Prefix von „wp_“ in „new_“ muss ich nur eine Stelle ändern – und zwar in der „wp_config.php“ und nicht meinen kompletten Code durchgehen, denn „.$wpdb->prefix."posts gibt mir „new_posts“ aus.

$wpdb->get_row

Wenn man also nur eine einzelne Zeile als Rückgabewert haben möchte, dann verwendet man $wpdb->get_row. In meinem folgenden Beispiel möchte ich beispielsweise alle Daten aus der Tabelle wp_post mit der ID = 1 und kann den post_title BMW ausgeben lassen.

function meinPlugin() {
	global $wpdb;
	$vehicle	=	$wpdb-> get_row("SELECT *  FROM ".$wpdb->prefix."posts WHERE ID = 1");
	echo $vehicle->post_title; // BMW
}

$wpdb->get_results

Mit $wpdb->get_results können mehrere Ergebnisse aus der WordPress Datenbank ausgelesen werden.

Im folgenden Beispiel möchte ich zum Beispiel alle Marken auslesen, die in der Kategorie „Autos“ gespeichert wurden.

function meinPlugin() {
	global $wpdb;
	$vehicles	=	$wpdb->get_results("SELECT *  FROM ".$wpdb->prefix."posts WHERE post_category LIKE 'Auto'");
	foreach ( $vehicles as $vehicle ) {
		echo 'Marke: ' . $vehicle->post_title;
	}
}

/*

AUSGABE:

Marke: BMW
Marke: Audi
Marke: Mercedes
Marke: Opel
Marke: Porsche
Marke: Autos

*/

Standardmäßig liefert $wpdb->get_results ein Array zurück. Daher nutze ich die foreach, um alle Daten als string auszugeben. Man könnte natürlich alle Werte auch als return wieder geben und diese dann später im Template verarbeiten. Zudem könnte man den SELECT auch noch anpassen und nur Marken ausgeben, die den „post_type“ post haben, aber es soll Euch ja auch nur als Beispiel dienen.

$wpdb->num_rows

Eine nützliche Funktion, wenn man nur die Anzahl der Treffer auslesen möchte, ist die Variable $wpdb->num_rows. Um dies zu veranschaulichen nutze ich das eben verwendete Beispiel.

function meinPlugin() {
	global $wpdb;
	$vehicles		=	$wpdb-> get_results("SELECT *  FROM ".$wpdb->prefix."posts WHERE post_category LIKE 'Auto'");
	$vehicles_count	=	$wpdb->num_rows;

	echo 'Treffer: ' . $vehicles_count;

/*
	Treffer: 6
*/
}

Im vorigen Beispiel habe ich die Markennamen ausgegeben. Aber in diesem Beispiel gibt $wpdb->num_rows die Anzahl der Treffer wieder und das ist in diesem Beispiel 6.

Die Rückgabewerte

Es gibt 3 mögliche Rückgabewerte, die $wpdb->get_row und $wpdb->get_results liefern.

Daten gefunden

Man erhält ein gefülltes Array.

Array ( 
	[0]	=>	stdClass Object ( [post_title] => BMW, [post_category] => Auto ) 
	[1]	=>	stdClass Object ( [post_title] => Audi, [post_category] => Auto ) 
	[2]	=>	stdClass Object ( [post_title] => Mercedes, [post_category] => Auto )
)

Keine Daten gefunden

Gibt ein leeres Array wieder.

Array ()

Fehler

Fehler bei der WordPress Datenbankabfrage mit wpdb.

NULL

Wenn wir also definitiv einen Rückgabewert aus unserer Funktion haben möchten können wir Sie wie folgt umschreiben:

function meinPlugin() {
	global $wpdb;
	$vehicles	=	$wpdb->get_results("SELECT *  FROM ".$wpdb->prefix."posts WHERE post_category LIKE 'Auto'");
	
	if( $vehicles !== NULL )  { // KEIN FEHLER
		if( !is_empty( $vehicles ) ) { // DATEN WURDEN GEFUNDEN
			foreach ( $vehicles as $vehicle ) {
				echo 'Marke: ' . $vehicle->post_title;
			}
		} else { // KEINE DATEN WURDEN GEFUNDEN
			echo 'Keine Treffer gefunden!';
		}
	} else { // WENN FEHLER
		echo 'Fehler';
	}
}

Mit den Abfragen der Rückgabewerte von wpdb seid Ihr auf jeden Fall auf der sicheren Seite und werdet definitiv Daten erhalten – im besten Falle natürlich die, die Ihr auch wollt 🙂

Fehlersuche bzw. Debugging

Ich glaube jeder kennt es – man weiß einfach nicht wo der Fehler vergraben liegt. Aber zum Glück gibt es mit $wpdb->show_errors() und $wpdb->print_error() zwei nützliche Helferlein im Kampf gegen die eigene Dummheit.

Vorab: Die Variable „Debugging“ muss in der Datei „wp_config.php“ auf true stehen!

$wpdb->show_errors()

Mit $wpdb->show_errors() kann man ganz gut falsch geschriebene Spaltennamen herausfinden. Wichtig ist zu wissen, dass $wpdb->show_errors() vor der Abfrage ausgeführt werden muss.

$wpdb->print_error()

Neben den Fehlern in der Abfrage kann es aber auch dazu kommen, dass sich Fehler in die SQL Anweisung geschlichen haben. Diese kann man mit $wpdb->print_error() sehr gut herausfinden. Diese muss aber unbedingt direkt nach der Abfrage ausgeführt werden. $wpdb->print_error() zeigt dann die vorherige SQL-Abfrage an und man kann relativ schnell sehen, wo der Fehler liegt.

Hinweis: Nach dem erfolgreichen Debuggen die Zeilen wieder aus den Code nehmen!

Abfragen vor SQL-Injection schützen

Eine der häufigsten Schwachstellen und ein gefundenes Fressen für Hacker sind Daten, die ungeschützt und ungeprüft übergeben und weiterverarbeitet werden. Dabei ist es so einfach seine Werte zu sichern. WordPress gibt uns sogar mit esc_sql() eine einfache aber sichere Funktion zu Hand, die wir unbedingt nutzen sollten!

function meinPlugin( $category ) {
	global $wpdb;
	
	$category_name	=	esc_sql( $category );
	
	$vehicles		=	$wpdb-> get_results("SELECT *  FROM ".$wpdb->prefix."posts WHERE post_category LIKE '" . $category_name . "'");
	$vehicles_count	=	$wpdb->num_rows;

	echo 'Treffer: ' . $vehicles_count;
}

Im Beispiel oben übergebe ich der Funktion meinPlugin den Kategorienamen. Dieser kann mittels $_POST oder $_GET übergeben worden sein und somit ein leichtes „Opfer“ für einen Hacker-Angriff. Also Fange ich $category ab und Escape die Variable und übergebe es einer neuen Variablen, mit der ich nun sicher weiterarbeiten kann.

oliver Ich heisse Oli und komme aus dem wuseligen Berlin. Meine Leidenschaft für Webseiten hält seit mehr 10 Jahren an. Dabei ist es egal ob ich kleinere oder größere Projekte umsetze - ich hänge mich in jedes Projekt mit voller Leidenschaft rein und versuche mich dabei immer wieder neu zu entdecken und neue Ideen umzusetzen.

Hinterlasse ein Kommentar

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.