WordPress: eine oder mehrere Kategorien aus dem Blog separieren

castle 1158201 1920
Quelle: Pixabay, extrabrandt

Um ein paar Beiträge für eine besondere Darstellung zu reservieren, zum Beispiel als Testimonials auf einer Seite, kann man einen zusätzlichen Inhaltstypen (Custom Post Type) definieren und einsetzen. Dieser hat automatisch sein eigenes Archiv ( http://example.com/posttypename ). Wenn man das nicht will, erreicht man die Separierung ausgewählter Beiträge auch, indem man eine oder mehrere Kategorien aus dem öffentlichen Blogteil ausschließt.

Das Beispiel entstand aus der Herausforderung, eine Kategorie (die für eine Testimonialseite reserviert werden sollte) aus dem öffentlichen Blogteil möglichst umfassend zu entfernen, und geht davon aus, dass Kategorien mit den IDs 6, 7 und 8 auszuschließen sind.

Der Loop

Über pre_get_posts werden Kategorien wie folgt aus dem Loop, dem »Letzte Beiträge«-Widget und der Posts-Pagination ausgefiltert (Achtung, nicht aus der Post Navigation, die meist im Template single.php zu finden ist, dazu später).

function pptf_exclude_categories_from_queries( $query ) { 
    if ( !is_admin() && !$query->get( 'cat' ) ) {
        $query->set( 'category__not_in', array(6,7,8) ); // Array ID oder IDs der Kategorie(n)
    }
}
add_action( 'pre_get_posts', 'pptf_exclude_categories_from_queries' );

Um die Kategorie direkt zu verwenden, if ( !is_admin() && !$query->get( 'cat' ) ) { ändern in if ( !is_admin() && !$query->get( 'cat' ) && !is_category() ) {, ansonsten sind die Beiträge nur über einen Custom Query verfügbar. Auf der Kategorieseite verhält sich das »Neueste Beiträge«-Widget dann entsprechend.

Das Kategorien-Widget

Der nächste Filter schließt Kategorie(n) aus dem »Kategorien«-Widget aus.

function pptf_exclude_categories_from_widget( $args ) {
     $args['exclude'] = array(6,7,8); // Array ID oder IDs der Kategorie(n)
     return $args;
}
add_filter( 'widget_categories_args', 'pptf_exclude_categories_from_widget', 10, 1 );

Das »Letzte Kommentare«-Widget

Nicht ganz so glatt geht das Filtern von Kommentaren vor sich, da get_comments kein Argument für Kategorien anbietet, allerdings post__not_in für auszufilternde Post IDs. Um die IDs zu ermitteln, ging ich den Weg über get_posts. An der Stelle bleibt allerdings abzuwägen, ob das Filtern von Kommentaren überhaupt erforderlich ist. Gibt man niemandem Gelegenheit dazu, Kommentare zu Beiträgen in versteckten Kategorien zu verfassen, erübrigt sich der nachfolgende Teil.

function pptf_get_post_ids_from_category() { 
    $args = array('category' => 6,7,8); // ID oder kommagetrennte Liste von IDs der Kategorie(n)
    $filter = get_posts($args);
    $post_ids = array();
    foreach($filter as $post) {
       $post_ids[] = $post->ID;
    }
    return($post_ids);
}

Anschließend entfernt der Filter die Kommentare zu den gesammelten Post-IDs aus dem »Letzte Kommentare«-Widget.

/* get_comments args */
function pptf_exclude_categories_from_comments( $args ) {
$args['post__not_in'] = pptf_get_post_ids_from_category(); 
    return $args;
}
add_filter( 'widget_comments_args', 'pptf_exclude_categories_from_comments', 10, 1 );

Das Archive Widget

function pptf_archives_join( $sql ) {
    global $wpdb;
    return $sql . " INNER JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id) INNER JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)";
}
add_filter( 'getarchives_join', 'pptf_archives_join' );
 
function pptf_archives_where( $sql ) {
    global $wpdb;
    $exclude = '6,7,8'; // kommgetrennte Kategorie-IDs.Liste
 return $sql . " AND $wpdb->term_taxonomy.taxonomy = 'category' AND $wpdb->term_taxonomy.term_id NOT IN ($exclude)";
}
add_filter( 'getarchives_where', 'pptf_archives_where' );

Post Navigation (single.php oder singular.php)

Bis hierher findet alles in der functions.php statt. Der letzte Filter betrifft die Post Navigation (Links zum jeweils vorherigem und nächstem Beitrag). Neuere Theme-Versionen verwenden hier vermutlich bereits die Funktion the_post_navigation.
Diese Funktion bekommt als zusätzliches Argument 'excluded_terms' => array(6,7,8),, Beispiel:

// Previous/next post navigation.
the_post_navigation( array(
    'next_text' => '<span class="meta-nav" aria-hidden="true">' . __( 'Next', 'my-theme-textdomain' ) . '</span> ' .
        '<span class="screen-reader-text">' . __( 'Next post:', 'my-theme-textdomain' ) . '</span> ' .
        '<span class="post-title">%title</span>',
    'prev_text' => '<span class="meta-nav" aria-hidden="true">' . __( 'Previous', 'my-theme-textdomain' ) . '</span> ' .
        '<span class="screen-reader-text">' . __( 'Previous post:', 'my-theme-textdomain' ) . '</span> ' .
        '<span class="post-title">%title</span>',
    'excluded_terms' => array(6,7,8),
 ) );

Andernfalls erhalten die beiden Funktionen next_post_link() und previous_post_link() das Argument zum Filtern der Kategorie(n).

Das Kalender-Widget

Dieses bietet mit get_calendar() nur einen Filter für den gesamten Output. Wer also Posts bestimmter Kategorien aus Kalenderlinks heraushalten will (Links auf Tage an denen ausschließlich Beiträge in versteckten Kategorien verfasst wurden, geben dann 404 zurück), hat derzeit keine andere Wahl (sofern es kein Plugin gibt, das mehr Flexibilität bietet), als den Output zu kopieren und entsprechend umzuschreiben, oder auf den Gebrauch des Kalender-Widgets zu verzichten.

3 Antworten zu „WordPress: eine oder mehrere Kategorien aus dem Blog separieren“

  1. nici-

    Hiho,

    wie genial, danke vielmals dafür!

    Das Ziel ist, Pressemeldungen separat vom eigentlichen Blogteil zu führen. Die sollten dann aber auch über ein Jahreszahlen-Archiv anspringbar/filterbar sein…

    Was mir dazu jetzt nur fehlt, ist also die Gegenseite: Ich brauche dann für die separierte Pressemeldungen-Kategorie ja sowohl einen Ausgabe-Loop, aber auch eine Archivwidget-Funktion. Wie mache ich das?

    Herzliche Grüße
    nici-

    1. Gaby

      Danke liebe Nici, lange her, dieser Spezialfall…
      Die Pressemeldungen werden als Beiträge verfasst und haben einfach eine eigene Kategorie? – Oder geht es hier um einen Custom Post Type? (Eigentlich egal, in beiden Fällen greift die WordPress Template-Hierarchie, man benötigt eigentlich keinen Custom Query, bei einer Kategorie).
      Wenn Pressemeldungen mit einem Standard Category-Term gekennzeichnet sind, kann dieser mit pre_get_posts einfach aus dem Haupt-Blogstream (index.php) rausgefiltert werden. Das native Kategorie-Archiv ist dennoch verfügbar unter seinem Link (z.B. example.com/category/pressemeldungen) – üblicherweise zuständig: category.php. Bei den Archiven ist beides zu haben nicht so einfach, weil sich hier alles auf derselben Template-Ebene abspielt (archive.php).
      Die Frage bei den datumsbasierten Archiven ist, was mit den anderen Kategorien passieren soll. Mit pre_get_posts gäbe es dann nur noch das Datums-Archiv für die ausgewählte Kategorie. Wenn es stattdessen zweierlei Archive geben soll, für die Pressekategorie und ein eigenes für den ganzen Rest, müsste das dann auch berücksichtigt werden. – Falls die Anforderung noch ungelöst ist, oder ich was missverstanden habe, bitte gerne per E-Mail (gaby@gby.at)

    2. Gaby

      Darüber bin ich heute gestolpert, vielleicht eine (Teil-)Lösung: https://plugins.twinpictures.de/premium-plugins/archive-pro-matic/

Bitte Kommentarfunktion nicht für Supportanfragen nutzen. Dem kann hier nicht entsprochen werden. Die Angabe einer E-Mail-Adresse und eines Namens ist nicht erforderlich. Einen (Spitz)-Namen zu nennen wäre aber doch nett.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Hinweis: Sowohl angegebener Name als auch E-Mail-Adresse (beides ist optional, dafür werden alle Kommentare vor Veröffentlichung geprüft) werden dauerhaft gespeichert. Du kannst jeder Zeit die Löschung Deiner Daten oder / und Kommentare einfordern, direkt über dieses Formular (wird nicht veröffentlicht, und im Anschluss gelöscht), und ich werde das umgehend erledigen. – Mit hinterlassenen Kommentaren hinterlegte IP-Adressen werden nach zwei Monaten automatisch gelöscht

publicly queryable