rss-icon mail-icon

Portfolio Christian Waldmann

Vom:
Anwendungsfälle für den WordPress  “posts_where” Filter

Blog

Mein "Kompendium" und sonstige Projekte

Anwendungsfälle für den WordPress “posts_where” Filter

WordPress hat viele unterschiedliche Einsprung-Punkte sogenannte Hooks. Einen, den ich als besonders mächtig einstufe, da er an vielerlei Stellen eingesetzt werden kann, ist der “posts_where” Filter. Mit Hilfe dieses Filters kann direkt der MySql-Query verändert werden, welcher dafür verantwortlich ist, welche Posts aus der Datenbank geladen werden. Da wir mit diesem Filter so nah am System sind, können hier besonders viele Fälle mit dem selben Filter verändert werden. Im Extremfall kann sogar die gesamte WHERE-Klausel verändert  und durch eine von uns geschriebene ersetzt werden.

Wann ist der Einsatz sinnvoll

Der Einsatz ist aus meiner Sicht dann sinnvoll, wenn  komplizierte Bedingungen vorherrschen. So darf,  z.B.,  ein Post  nicht in der Suche auftauchen, nicht als Post angezeigt werden, aber als Ausgabe auf einer statischen Seite (Page) angezeigt sein.

Wo platziere ich am besten diesen Hook

Je nach dem wie der Hook eingesetzt werden soll, kann es sinnvoll sein, ihn an unterschiedlichen Stellen zu registrieren. Die einfachste Möglichkeit diesen zu registrieren ist sicherlich in der function.php des Templates. Andererseits ist es aus meiner Sicht sinnvoller, diesen in ein Plugin einzubauen (wenn es nicht sogar von einem “größeren” Plugin eingesetzt wird). Dies hat zwei Vorteile:

  1. Ihr müsst die function.php nicht mit unnötigem Code aufblähen.
  2. Wenn ihr den Code in ein Plugin auslagert, könnt ihr dieses nach Belieben deaktivieren oder aktivieren, ohne eine Datei editieren zu müssen und dies bequem über das Admin-Interface erledigen.

Wie registriere ich den Hook?

Registrieren könnt ihr den Hook mit folgendem Aufruf:

add_filter('posts_where', 'cmd_manipulate_post_where' );

function cmd_manipulate_post_where ($where){
	//do something

	return $where;
}

Mögliche Einsatzgebiete von “posts_where”

Posts excludieren

Es gibt mit Sicherheit einfachere Wege, Beiträge aus der Loop zu excludieren, aber keinen, der so gezielt wirkt und gleichzeitg so flexibel eingesetzt werden kann – (wer einfach “nur” Beiträge excludieren will, findet im Web etliche gute Beispiele dazu). Der Vorteil hier ist, dass ich extrem gut steuern kann, wann ein Beitrag angezeigt wird oder nicht.

Beispiel: Ich möchte verhindern das ein Post mit einem bestimmen Wort in der Headline nicht in der Suche auftaucht. Da wir direkt den MySql-Query verändern können, ist es möglich, dass wir den relativ bequemen Weg über reguläre Ausdrücke gehen.

add_filter('posts_where', 'cmd_manipulate_post_where' );

function cmd_manipulate_post_where ($where){
	if (is_search ()) {
		global $wpdb;
		$where .= " AND $wpdb->posts.post_title NOT REGEXP '^.*schlechtes Wort.*$'";
	}

	return $where;
}
Einen Post auf jeder Seite zusätzlich einfügen

Manchmal verlangen Kunden wünsche zu etwas abwägigen Kombinationen. In diesem konkreten Fall war es (temporär) notwendig auf jeder Seite einen zusätzlichen Beitrag auszugeben (auch in der Suche). Relativ schnell gelöst werden konnte dies mit Hilfe des Filters. Konstruiert war das ganze als Plugin, sodass der Kunde den zusätzlichen Beitrag nach belieben an und wieder abschalten konnte.

add_filter('posts_where', 'cmd_manipulate_post_where' );

function cmd_manipulate_post_where ($where){
	if (!is_home()) {
		global $wpdb;
		$where .= " OR $wpdb->posts.ID = 1";
	}

	return $where;
}
Die ausgegebenen Post komplett ändern

Durch weglassen des “.” vor dem “=” kann die komplette WHERE-Klausel überschrieben werden. Jedoch darf das “AND” nicht vergessen werden, da WordPress die Where Bedinungen an eine nicht vom Filter betroffene Bedinung hängt.

add_filter('posts_where', 'cmd_manipulate_post_where' );

function cmd_manipulate_post_where ($where){
	if (is_home()) {
		global $wpdb;
		$where = " AND $wpdb->posts.ID = 83";
	}
	return $where;
}
Posts mit einem bestimmten Tag aus der Suche ausschließen
add_filter('posts_where', 'cmd_manipulate_post_where' );

function cmd_manipulate_post_where ($where){
	if (is_search()) {
		global $wpdb;
		//Entfernt Beiträge Tags: 10,4 und 7 (Ids)
		$filter =  " AND tt.term_id IN ('10', '4', '7')";
		$where .= " AND $wpdb->posts.ID NOT IN ";
		$where .= "(SELECT tr.object_id FROM $wpdb->term_relationships AS tr INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy = 'post_tag'".$filter.")";
	}

	return $where;
}

Fazit

Dieser Hook ist vielseitig einsetzbar. Ich habe hier nur einige der Möglichkeiten aufgezählt um eine erste Ahnung zu vermitteln wie dieser eingesetzt werden kann. Die meisten der oben angegebenen Anwedungen habe ich so oder so ähnlich bereits angewendet. Sicherlich gibt es für die meisten Einsatzmöglichkeiten einfachere Lösungen, jedoch ist gerade bei komplizierten Bedinungen dieser Hook die bessere Wahl.