WordPress: Schlagwortwolke (Tag-Cloud) aus Kategorien
Update vom 20. Dezember 2012: Der Widget unten wird demnächst als WordPress-Plugin freigegeben, damit man nicht immer den Code im Theme selber einbauen muss.
Mit einer Schlagwortwolke (Tag-Cloud) kann man sehr einfach eine Liste von Schlagwörtern kompakt und übersichtlich darstellen. Hier ein Beispiel aus unserer Webseite:
Man kann mit folgender Funktion eine Schlagwortwolke programmatisch anzeigen:
Zusätzlich zu diesen Parameter kann man auch exclude
verwenden, um bestimmte Tags auszuschließen. Umgekehrt mit include
kann man eine Liste von Tags definieren, die angezeigt werden sollen.
Wenn man aber einen Bereich hat, wo man nur ein Teil der Artikel sehen kann d.h. nur eine oder mehrere Kategorien, macht es Sinn in der Tag-Cloud nur die Tags anzuzeigen, womit Artikel aus dieser Kategorie bzw. aus diesen Kategorien markiert wurden. Die include
Option von wp_tag_cloud
zu verwenden ist keine gute Lösung, da man die Liste dann ständig erweitern muss. Am besten wäre es, wenn man einfach eine Liste von Kategorien definieren könnte, die berücksichtigt werden müssen. Das kann man leider mit dem Tag-Cloud-Widget in WordPress nicht erreichen. Aber kann mit dem hier vorgestellten Widget gemacht werden.
Man kann den Titel des Widgets konfigurieren und auch eine oder mehrere Kategoriene aus der Liste aller Kategorien wählen:
Es werden dann alle Tags angezeigt, womit Artikel in einer dieser Kategorien markiert wurden. Ein Beispiel davon kann man hier rechts sehen.
Hier der Code zum Widget:
'widget_cat_tag_cloud', 'description' => __( "Tag cloud for a specific category") ); $this->WP_Widget('cat_tag_cloud', __('aw - "Category Tag Cloud"'), $widget_ops); } function widget($args, $instance) { extract($args); global $wpdb; $title = apply_filters('widget_title', empty($instance['title']) ? '' : $instance['title'], $instance, $this->id_base); $tags = $wpdb->get_results (" SELECT DISTINCT tt2.term_id AS tag_id FROM wp_posts as posts INNER JOIN wp_term_relationships as tr1 ON posts.ID = tr1.object_ID INNER JOIN wp_term_taxonomy as tt1 ON tr1.term_taxonomy_id = tt1.term_taxonomy_id INNER JOIN wp_term_relationships as tr2 ON posts.ID = tr2.object_ID INNER JOIN wp_term_taxonomy as tt2 ON tr2.term_taxonomy_id = tt2.term_taxonomy_id WHERE tt1.taxonomy = 'category' AND posts.post_status = 'publish' AND tt1.term_id IN (".implode(",",$instance['category_id']).") AND tt2.taxonomy = 'post_tag' "); foreach ($tags as $tag) { $includeTags = $tag->tag_id .',' . $includeTags; } $cloud_args = array('include'=>$includeTags); echo $before_widget; if ( $title ) echo $before_title . $title . $after_title; ?>
Wenn der Widget oben in der Datei aw-widgets.php
im Theme gespeichert wurde, kann man den Widget im Theme aktivieren, in dem man folgendes in functions.php
einfügt:
include_once('aw-widgets.php');
Der Widget macht folgendes:
Es wird eine Liste von Kategorie-IDs im Widget definiert. Der Widget führt dann eine SQL-Abfrage, um eine Liste von relevanten Tags zu bekommen. Der WordPress 3 Modell sieht so aus:
Die relevante Tabellen haben eine blaue Kopfzeile.
Beide Kategorien und Tags sind Terms. Sie sind also in der Tabelle wp_terms
gespeichert und werden durch eine term_id
identifiziert. Ob es sich um eine Kategorie oder einen Tag wird mit der Zuweisung einer Taxonomie definiert. Es geschieht, wenn die term_id
in der wp_term_taxonomy
Tabelle referenziert wird. Wenn man nur mit der term_id arbeitet, braucht man also die wp_terms
Tabelle nicht, dann reicht nämlich die wp_term_taxonomy
Tabelle.
Um alle Tags zu holen, kann man folgende SQL-Abfrage ausführen:
SELECT DISTINCT tt.term_id AS tag_id FROM wp_term_taxonomy as tt WHERE tt2.taxonomy = 'post_tag'
Ähnlich kann man die Kategorien holen:
SELECT DISTINCT tt.term_id AS category_id FROM wp_term_taxonomy as tt WHERE tt2.taxonomy = 'category'
Wenn man jetzt nach Tags die zu einem Artikel gehören, muss man die wp_term_taxonomy
Tabelle mir der wp_posts
Tabelle verbinden. Man kann sie nicht direkt sondern über die wp_term_relationships
Tabelle verbinden.
SELECT DISTINCT posts.ID FROM wp_posts as posts INNER JOIN wp_term_relationships as tr ON posts.ID = tr.object_ID INNER JOIN wp_term_taxonomy as tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy = 'category' AND posts.post_status = 'publish' AND tt.term_id IN (xxx, yyy, zzz)
Man bekommt so eine Liste von allen Posts in einer diesen 3 Kategorien. Jetzt muss man nur noch die Tags für diesen Artikel finden:
SELECT DISTINCT tt.term_id AS tag_id FROM wp_posts as posts INNER JOIN wp_term_relationships as tr ON posts.ID = tr.object_ID INNER JOIN wp_term_taxonomy as tt ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy = 'post_tag' AND posts.post_status = 'publish' AND posts.ID IN (xxx, yyy, zzz)
Man bekommt so alle Tags für diese 3 Posts. Wenn man jetzt beide Abfragen kombiniert:
SELECT DISTINCT tt2.term_id AS tag_id FROM wp_posts as posts INNER JOIN wp_term_relationships as tr1 ON posts.ID = tr1.object_ID INNER JOIN wp_term_taxonomy as tt1 ON tr1.term_taxonomy_id = tt1.term_taxonomy_id INNER JOIN wp_term_relationships as tr2 ON posts.ID = tr2.object_ID INNER JOIN wp_term_taxonomy as tt2 ON tr2.term_taxonomy_id = tt2.term_taxonomy_id WHERE tt1.taxonomy = 'category' AND posts.post_status = 'publish' AND tt1.term_id IN (".implode(",",$instance['category_id']).") AND tt2.taxonomy = 'post_tag'
Wenn man dann eine Liste von Tags hat, kann man einfach das include
Attribut beim Aufruf der wp_tag_cloud
Funktion verwenden, um die neue Schlagwortwolke anzuzeigen.