Keine Sub-Kategorien im Loop von WordPress

Nicht immer soll die Ausgabe des Loop innerhalb einer Kategorie die Unterkategorien enthalten. Um das zu bewerkstelligen kann man einen eigene WP Query bauen und jeweils ein Template erstellen, siehe einige Tipps und Hinweis dazu in einem anderen Beitrag von mir. Alternativ kann man aber auch einen Hook nutzen und alle Unterkategorien zu filtern. Die folgende Syntax ablegen in der functions.php des Themes oder in ein Plugin auslagern und fertig. Alternativ kann man diesen Hook aber auch zu anderen Sachen benutzen. Auch dazu möchte ich hier einige Worte verlieren.

Die Zeiten ändern sich.

Dieser Beitrag scheint älter als 9 Jahre zu sein – eine lange Zeit im Internet. Der Inhalt ist vielleicht veraltet.

Nicht immer soll die Ausgabe des Loop innerhalb einer Kategorie die Unterkategorien enthalten. Um das zu bewerkstelligen kann man einen eigene WP Query bauen und jeweils ein Template erstellen, siehe einige Tipps und Hinweis dazu in einem anderen Beitrag von mir. Alternativ kann man aber auch einen Hook nutzen und alle Unterkategorien zu filtern. Die folgende Syntax ablegen in der functions.php des Themes oder in ein Plugin auslagern und fertig.

Alternativ kann man diesen Hook aber auch zu anderen Sachen benutzen. Auch dazu möchte ich hier einige Worte verlieren.

Der Hook posts_where ist eine wichtige Möglichkeit um auf den Query von WordPress Einfluss zu nehmen und daher ein Bestandteil des Query: $where = apply_filters('posts_where', $where);. Er dient beispielsweise dazu, den Query von WordPress zu erweitern. Dabei wird immer ein Parameter übergeben. Dieser kann mit jede Art von SQL-Anweisungen befüllt werden.

Ein bekanntes Beispiel ist eventuell mein Artikel zum verspäteten Veröffentlichen von Feeds: „WordPress Feed zeitversetzt befüllen“.

Eine weitere Möglichkeit ist es, wie schon im Eingang angesprochen, dass bei der Ausgabe innerhalb von Kategorien die Unterkategorien nicht gelistet werden sollen. Die folgende Syntax tut genau dies.


if ( !function_exists('fb_filter_child_cats') ) {
	function fb_filter_child_cats( $cats= '' ) { 
		global $wp_query, $wpdb;
	
		if ( is_category() ) {
			
			// get children ID's
			if ( $excludes = get_categories( "child_of=" . $wp_query->get('cat') ) ) {
				
				// set array with ID's
				foreach ( $excludes as $key => $value ) {
					$exclude[] = $value->cat_ID;
				}
			}
			
			// remove child cats
			if ( isset($exclude) && is_array($exclude) ) {
				$cats .= " AND " . $wpdb->prefix . "term_taxonomy.term_id NOT IN (" . implode(",", $exclude) . ") ";
			}
		}
		
		return $cats;
	}
	
	if ( !is_admin() ) {
		add_filter( 'posts_where', 'fb_filter_child_cats' );
	}
}

Um ein stabileres Ergebnis zu erzielen, sollte man möglichst SQL Selects umgehen und damit stabiler in WP zu bleiben. Daher hier eine weitere Lösung für die Filterung der Kinder-Kategorien:


function fb_filter_child_cats($query) {

	$cat = get_term_by( 'name', $query->query_vars['category_name'], 'category' );
	
	if ( ! isset( $cat->term_id ) )
		return $query;
	
	$child_cats = (array) get_term_children( $cat->term_id, 'category' );
	// also possible
	// $child_cats = (array) get_term_children( get_cat_id($query->query_vars['category_name']), 'category' );
	
	if ( ! $query->is_admin )
		$query->set( 'category__not_in', array_merge( $child_cats ) );
	
	return $query;
}
add_filter( 'pre_get_posts', 'fb_filter_child_cats' );

Ein weiteres Beispiel soll zeigen, wie man den Query erweitert. Dabei beziehe ich mich auf einige Fragen aus der WP Hacker Mailingliste, die eigentlich dort nicht hingehören, dazu ist das Forum da.
In die Funktion habe ich mal drei Beispiele integriert.

  • Beiträge der Zukunft im Loop
  • Seiten im Loop
  • Nur Beiträge im Loop, die älter als 5 Tage sind

Ich hoffe, dass die Möglichkeiten damit recht gut dargestellt werden.


if ( !function_exists('fb_filter_where') ) {
	function fb_filter_where( $where = '' ) {
		global $wpdb;
		
		// allow future posts in loop
		$where .= " OR $wpdb->posts.post_status = 'future' ";
		
		// show pages in loop
		$where .= " OR $wpdb->posts.post_type = 'page' ";
		
		// only older (<) as 5 days
		$where .= " AND post_date < '" . date('Y-m-d', strtotime('-5 days')) . "'";
		
		return $where;
	}
	
	if ( !is_admin() ) {
		add_filter( 'posts_where', 'fb_filter_where' );
	}
}

Die Möglichkeiten sind sehr flexibel und im Grunde nur abhängig von den SQL-Abfragen. Damit sollte der Hook ein wenig verständlicher sein und seine vielseitigen Möglichkeiten lassen sich nur annähernd darstellen. Dieser Hook ist nur einer von vielen Hooks, die die Flexibilität von WordPress auszeichnen.

Kommentare sind geschlossen.