Beiträge aus Kategorien in WordPress abrufen, Entwickleranleitung

Beiträge aus Kategorien in WordPress abrufen, Entwickleranleitung

Zuletzt überprüft: 12. Oktober 2026
17 Min. Lesezeit
Tutorial
500+ WP-Projekte
Full-Stack-Entwickler

#WordPress Beiträge einer Kategorie anzeigen

Erfahren Sie mehr über professionelle WordPress-Entwicklung bei WPPoland. Eine der häufigsten Aufgaben in der WordPress-Entwicklung ist das Abrufen von Beiträgen aus bestimmten Kategorien. Egal ob Sie ein benutzerdefiniertes Homepage-Layout erstellen, ein Kategoriearchiv-Template anlegen oder verwandte Inhalte anzeigen möchten: Effizientes Abfragen von Beiträgen nach Kategorie ist für jeden WordPress-Entwickler unverzichtbar.

Dieser Leitfaden behandelt praxiserprobte Ansätze zum Abrufen von Beitraegslisten aus Kategorien, von einfachen Implementierungen bis hin zu fortgeschrittenen Optimierungstechniken. Am Ende verfügen Sie über ein vollständiges Werkzeugset für kategoriebasierte Abfragen in jedem WordPress-Projekt.

#Wie WordPress Kategorien speichert

Bevor wir mit dem Code beginnen, ist es wichtig zu verstehen, wie WordPress Kategorien handhabt:

  • Kategorien sind eine integrierte Taxonomie in WordPress
  • Jeder Beitrag kann mehreren Kategorien angehören
  • Kategorien können hierarchisch sein (Eltern-Kind-Beziehungen)
  • Kategoriedaten werden in den Tabellen wp_terms und wp_term_taxonomy gespeichert
  • Beitrag-Kategorie-Beziehungen werden in wp_term_relationships gespeichert

Das Verständnis dieser Struktur hilft dabei, effizientere Abfragen zu schreiben und Probleme zu lösen.

#Eine Kategorie-ID aus Slug oder Name ermitteln

Die meisten Abfrageargumente akzeptieren wahlweise einen Slug oder eine numerische ID, aber die ID-basierten Argumente (cat, category__in) sind am schnellsten, weil sie den Term-Lookup überspringen. Wenn Sie nur den Slug kennen, lösen Sie ihn einmal auf und verwenden die ID weiter:

// From a slug
$term = get_category_by_slug('news');
$news_id = $term ? $term->term_id : 0;

// From a display name
$news_id = get_cat_ID('News'); // returns 0 if not found

// From any taxonomy (categories included)
$term = get_term_by('slug', 'news', 'category');

In der Praxis wird das gern übersehen: Hinterlegen Sie die aufgelöste ID in einer Konstante oder Option, wenn Sie sie fest in einem Template verdrahten. Ein get_cat_ID() bei jedem Seitenaufruf erzeugt eine vermeidbare Datenbankabfrage.

#Beiträge nach Kategorie mit WP_Query abfragen

WP_Query ist die primäre WordPress-Klasse für das Abfragen von Beiträgen. Sie bietet maximale Flexibilität und ist der empfohlene Ansatz für die meisten Anwendungsfaelle.

#Abfrage nach Kategorie-Slug

$args = array(
    'category_name' => 'news',
    'posts_per_page' => 10,
    'orderby' => 'date',
    'order' => 'DESC'
);

$query = new WP_Query($args);

if ($query->have_posts()) {
    while ($query->have_posts()) {
        $query->the_post();
        // Beitragsinhält anzeigen
        ?>
        <article>
            <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
            <div class="entry-content">
                <?php the_excerpt(); ?>
            </div>
        </article>
        <?php
    }
    wp_reset_postdata();
}

#Abfrage nach Kategorie-ID

$args = array(
    'cat' => 5, // Kategorie-ID
    'posts_per_page' => 5
);

$query = new WP_Query($args);

#Beiträge aus mehreren Kategorien abfragen

// Beiträge in EINER BELIEBIGEN dieser Kategorien (ODER-Beziehung)
$args = array(
    'category__in' => array(5, 10, 15),
    'posts_per_page' => 10
);

// Beiträge in ALLEN diesen Kategorien (UND-Beziehung)
$args = array(
    'category__and' => array(5, 10),
    'posts_per_page' => 10
);

// Bestimmte Kategorien ausschließen
$args = array(
    'category__not_in' => array(3, 7),
    'posts_per_page' => 10
);

#Unterkategorien in WP_Query einschließen

// Beiträge aus Kategorie und allen Unterkategorien abrufen
$parent_category_id = 5;

$args = array(
    'cat' => $parent_category_id,
    'posts_per_page' => 20
);

// WP_Query schließt Unterkategorien automatisch ein, wenn 'cat' verwendet wird

#Kategorie-Abfrage auf einer statischen Startseite paginieren

Eine eigene Schleife paginiert über paged, das Sie mit get_query_var( 'paged' ) auslesen. Die Ausnahme ist ein Seiten-Template, das als statische Startseite eingestellt ist: Dort legt WordPress die Seitenzahl in der Variable page ab, deshalb verweist die WP_Query-Referenz auf get_query_var( 'page' ). Mit der falschen Variable zeigt jeder Klick auf “weiter” wieder Seite eins.

$paged = ( is_front_page() && is_page() ) ? get_query_var( 'page' ) : get_query_var( 'paged' );
$paged = max( 1, (int) $paged );

$query = new WP_Query( array(
    'category_name'  => 'nachrichten',
    'posts_per_page' => 10,
    'paged'          => $paged,
) );

#Welche Kategorie-Parameter Unterkategorien einbeziehen

Dieselbe Kategorie-ID liefert unterschiedliche Beitragslisten, je nachdem, über welche Schnittstelle Sie sie abfragen. Hinter den meisten Meldungen der Art “in der Liste fehlen Beiträge” steckt genau dieses Detail, und die Regeln stehen im Core-Code, nicht in Einstellungen:

SchnittstelleArgumentBeiträge aus Unterkategorien
WP_Querycatenthalten
WP_Querycategory_nameenthalten
WP_Querycategory__in, category__and, category__not_innicht enthalten
WP_Querytax_queryenthalten, außer include_children ist false
get_posts()categoryenthalten (Alias von cat)
REST-APIcategories=5nicht enthalten
REST-APIcategories[terms]=5&categories[include_children]=trueenthalten
Query-Loop-BlockKategoriefilternicht enthalten
WP-CLI--cat, --category_nameenthalten (gehen direkt an WP_Query)

Die WP_Query-Zeilen stammen aus WP_Query::parse_tax_query(): cat wird zu einer Tax Query mit include_children auf true, category__in, category__and und category__not_in werden zu Tax Queries mit include_children auf false. Die WP_Query-Referenz sagt in ihren Beispielen dasselbe: category__in zeigt keine Beiträge aus Unterkategorien. Die Zeile zu get_posts() folgt aus der Funktionsreferenz, die category als Alias von cat beschreibt. Die REST-Zeilen kommen aus dem Posts-Controller, in dem include_children standardmäßig false ist und nur für hierarchische Taxonomien angeboten wird. Die Query-Loop-Zeile kommt aus build_query_vars_from_query_block() in der blocks.php des Cores, die für jeden Taxonomiefilter fest include_children => false setzt.

Die praktische Folge: Ein PHP-Template mit cat => 5 und ein Headless-Frontend, das /wp/v2/posts?categories=5 aufruft, können für dieselbe Elternkategorie verschiedene Beiträge zeigen. Legen Sie fest, welches Verhalten Sie brauchen, und wählen Sie das Argument, das es liefert, statt anzunehmen, dass beide übereinstimmen.

#get_posts() mit Kategorie verwenden

Für einfachere Anwendungsfaelle bietet get_posts() eine unkompliziertere API.

#get_posts() mit Kategorie-ID

$posts = get_posts(array(
    'category' => 5,
    'posts_per_page' => 10,
    'orderby' => 'date',
    'order' => 'DESC'
));

foreach ($posts as $post) {
    setup_postdata($post);
    ?>
    <article>
        <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
    </article>
    <?php
}
wp_reset_postdata();

#get_posts() mit Kategoriename

$posts = get_posts(array(
    'category_name' => 'technology',
    'numberposts' => 5
));

#Was get_posts gegenüber WP_Query ändert

get_posts() ist eine dünne Hülle, die ein WP_Query mit eigenen Standardwerten baut. Der Quellcode der Funktion zeigt vier Unterschiede, die bei Kategorielisten zählen:

  • numberposts steht standardmäßig auf 5, ein Aufruf ohne Limit liefert also stillschweigend fünf Beiträge.
  • post_status steht auf publish und suppress_filters auf true, daher laufen posts_where und ähnliche SQL-Filter von Plugins nicht. Die Action pre_get_posts feuert trotzdem.
  • ignore_sticky_posts und no_found_rows werden immer auf true gezwungen. Eine nummerierte Paginierung lässt sich auf get_posts() nicht aufbauen, weil die Gesamtzahl nie berechnet wird.
  • include setzt posts_per_page auf die Anzahl der übergebenen IDs und überschreibt Ihr eigenes Limit.

Eine weitere Falle betrifft get_posts() innerhalb einer Funktion oder eines Shortcode-Callbacks. setup_postdata() bereitet die Template-Tags vor, aber the_title() und the_permalink() lesen weiterhin das globale $post. Deklarieren Sie global $post; vor der Schleife foreach ( $posts as $post ), wie es die Beispiele der Funktionsreferenz tun, und schließen Sie mit wp_reset_postdata() ab. Ohne diese Deklaration gibt jeder Listeneintrag den Titel der Seite aus, auf der der Shortcode steht.

#Eine Kategorie aus einer WordPress-Abfrage ausschließen

Ausschließen funktioniert auf zwei Wegen, und beide behandeln Unterkategorien unterschiedlich. Eine negative ID in cat schließt die Kategorie samt Unterkategorien aus, weil der Core eine NOT IN-Tax-Query mit include_children auf true baut. category__not_in schließt nur die genannten Terme aus, Beiträge in einer Unterkategorie erscheinen also weiterhin.

// Schließt Kategorie 12 und alle ihre Unterkategorien aus
$args = array( 'cat' => '-12' );

// Schließt nur Beiträge aus, die direkt in 12 oder 34 liegen
$args = array( 'category__not_in' => array( 12, 34 ) );

Um eine Kategorie von der Blog-Startseite fernzuhalten, ändern Sie die Hauptabfrage, statt eine zweite Schleife laufen zu lassen. Die Referenz zu pre_get_posts empfiehlt genau diese Bedingungen:

add_action( 'pre_get_posts', function ( $query ) {
    if ( ! is_admin() && $query->is_main_query() && $query->is_home() ) {
        $query->set( 'cat', '-12' );
    }
} );

#Shortcode für Beiträge einer Kategorie

Das Erstellen eines Shortcodes ermöglicht es Content-Editoren, Kategorie-Beitraegslisten überall einzufügen.

function category_posts_shortcode($atts) {
    $atts = shortcode_atts(array(
        'category' => '',
        'posts' => 5,
        'orderby' => 'date',
        'order' => 'DESC'
    ), $atts);
    
    $args = array(
        'category_name' => $atts['category'],
        'posts_per_page' => intval($atts['posts']),
        'orderby' => $atts['orderby'],
        'order' => $atts['order']
    );
    
    $query = new WP_Query($args);
    
    ob_start();
    
    if ($query->have_posts()) {
        echo '<div class="category-posts-list">';
        while ($query->have_posts()) {
            $query->the_post();
            ?>
            <article class="category-post">
                <h3><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
                <p><?php the_excerpt(); ?></p>
            </article>
            <?php
        }
        echo '</div>';
    } else {
        echo '<p>Keine Beiträge in dieser Kategorie gefunden.</p>';
    }
    
    wp_reset_postdata();
    
    return ob_get_clean();
}
add_shortcode('category_posts', 'category_posts_shortcode');

Verwendung: [category_posts category="news" posts="5"]

#Kategoriearchiv mit pre_get_posts anpassen

Wenn Sie ändern möchten, welche Beiträge auf Kategoriearchivseiten erscheinen, verwenden Sie die pre_get_posts-Action.

function modify_category_queries($query) {
    // Nur Kategoriearchive in der Hauptabfrage modifizieren
    if ($query->is_category() && $query->is_main_query() && !is_admin()) {
        // 20 Beiträge pro Seite statt des Standardwerts anzeigen
        $query->set('posts_per_page', 20);
        
        // Beiträge aus bestimmter Kategorie auf bestimmten Kategorieseiten ausschließen
        $current_cat = get_queried_object();
        if ($current_cat->slug === 'featured') {
            $query->set('category__not_in', array(10)); // Kategorie mit ID 10 ausschließen
        }
    }
}
add_action('pre_get_posts', 'modify_category_queries');

Verwenden Sie im Callback die Methodenversionen der Conditional Tags ($query->is_category(), $query->is_main_query()). Die freien Funktionen prüfen das globale $wp_query und nicht das Abfrageobjekt, das der Hook übergibt, worauf die Hook-Referenz ausdrücklich hinweist.

#Warum query_posts zum Filtern nach Kategorie ungeeignet ist

Ältere Anleitungen setzen query_posts( 'cat=5' ) an den Anfang eines Templates. Der Docblock von query_posts() im Core sagt, dass die Funktion die Hauptabfrage vollständig überschreibt, nicht für Plugins oder Themes gedacht ist und in den meisten Fällen durch die Action pre_get_posts ersetzt werden sollte. Der Funktionskörper ist eine einzige Zeile, die dem globalen $wp_query ein neues WP_Query zuweist. Ein Template läuft nach der Hauptabfrage, der Aufruf wiederholt also die Datenbankarbeit und ersetzt das Objekt, aus dem Paginierung und Conditional Tags lesen. Jede Kategorie-Aufgabe, die query_posts() nutzte, lässt sich mit pre_get_posts (Archiv ändern) oder einem separaten WP_Query (zweite Liste) lösen.

#Beiträge nach Kategorie mit tax_query filtern

Die Abkürzungen cat und category_name sind bequem, aber tax_query ist das Argument der Wahl, sobald die Anforderungen konkret werden: Kategorien mit Schlagwörtern kombinieren, Unterkategorien ausschließen oder eine eigene Taxonomie abfragen. Außerdem drücken Sie damit UND/ODER-Logik ausdrücklich aus, was die Abkuerzungsargumente nicht können.

$args = array(
    'posts_per_page' => 10,
    'tax_query' => array(
        'relation' => 'AND',
        array(
            'taxonomy' => 'category',
            'field'    => 'slug',
            'terms'    => array('news'),
        ),
        array(
            'taxonomy' => 'post_tag',
            'field'    => 'slug',
            'terms'    => array('featured'),
        ),
    ),
);

$query = new WP_Query($args);

Der Schlüssel include_children ist das praktische Detail, das die meisten übersehen. Standardmäßig zieht eine category-tax_query jeden untergeordneten Term mit hinein, was für ein Archiv meist erwünscht ist, für einen kuratierten Homepage-Block aber selten:

'tax_query' => array(
    array(
        'taxonomy'         => 'category',
        'field'            => 'term_id',
        'terms'            => array(5),
        'include_children' => false, // only posts filed directly under term 5
    ),
),

Da tax_query gegen jede beliebige Taxonomie arbeitet, ruft dasselbe Muster Beiträge aus einer eigenen product_cat, portfolio_type oder jeder Taxonomie ab, die Ihr Theme registriert, ohne eine separate Funktion pro Taxonomie.

Kategoriefilter lassen sich auch mit benutzerdefinierten Feldern kombinieren. Eine Veranstaltungsliste, die nur kommende Termine aus zwei Kategorien zeigt, verbindet category__in mit einer meta_query und sortiert nach dem Datumsfeld:

$args = array(
    'posts_per_page' => 10,
    'category__in'   => array( get_cat_ID( 'Konferenzen' ), get_cat_ID( 'Workshops' ) ),
    'meta_key'       => 'event_datum',
    'orderby'        => 'meta_value',
    'order'          => 'ASC',
    'meta_query'     => array(
        array(
            'key'     => 'event_datum',
            'value'   => current_time( 'Y-m-d' ),
            'compare' => '>=',
            'type'    => 'DATE',
        ),
    ),
);

get_cat_ID() erwartet den Kategorienamen, nicht den Slug, und gibt 0 zurück, wenn nichts passt. Eine 0 in category__in trifft keinen Beitrag, prüfen Sie die IDs also, bevor die Abfrage auf einer Produktivseite läuft.

#Kategorieabfragen mit Caching beschleunigen

#1. Transients für aufwändige Abfragen verwenden

function get_cached_category_posts($category_id, $count = 5) {
    $cache_key = 'cat_posts_' . $category_id . '_' . $count;
    $posts = get_transient($cache_key);
    
    if (false === $posts) {
        $args = array(
            'cat' => $category_id,
            'posts_per_page' => $count
        );
        
        $query = new WP_Query($args);
        $posts = $query->posts;
        
        // Cache für 1 Stunde
        set_transient($cache_key, $posts, HOUR_IN_SECONDS);
    }
    
    return $posts;
}

#2. Datenbankabfragen optimieren

// Nur benoedigte Felder abrufen
$args = array(
    'category_name' => 'news',
    'posts_per_page' => 10,
    'fields' => 'ids' // Nur Post-IDs für bessere Performance abrufen
);

$query = new WP_Query($args);

Das Argument fields akzeptiert laut WP_Query-Referenz genau drei Werte: all (Standard), ids und id=>parent. Jeder andere Wert, auch ein Array mit Spaltennamen, liefert stillschweigend vollständige Beitragsobjekte. Zwei weitere Schalter sparen Arbeit bei Listen, die nur Titel und Link ausgeben:

$args = array(
    'category_name'          => 'nachrichten',
    'posts_per_page'         => 5,
    'no_found_rows'          => true,  // kein SQL_CALC_FOUND_ROWS, keine Paginierung nötig
    'update_post_meta_cache' => false, // benutzerdefinierte Felder werden nicht ausgegeben
    'update_post_term_cache' => false, // Terme werden nicht ausgegeben
);

no_found_rows verhindert, dass WordPress die Gesamtzahl der Treffer zählt, die es nur für die Paginierung braucht. Die beiden Cache-Flags stehen im Core standardmäßig auf true; laut Referenz muss man sie normalerweise nicht anfassen, doch abgeschaltet sparen sie die zusätzlichen Meta- und Term-Abfragen, wenn die Liste diese Daten nie liest. Lassen Sie sie an, wenn die Schleife Kategorien, Schlagwörter oder benutzerdefinierte Felder ausgibt, denn das Vorladen in einer Abfrage ist günstiger als eine Abfrage pro Beitrag.

#3. Object Caching verwenden

Wenn Ihre Website einen Object Cache (Redis, Memcached) verwendet, werden WP_Query-Ergebnisse automatisch gecacht, was die Performance bei wiederholten Abfragen verbessert.

#Kategorie-Templates, AJAX, Query Loop und REST-API

#Benutzerdefinierte Templates für Kategoriearchive

Erstellen Sie eine Template-Datei category-news.php für kategoriespezifisches Styling:

<?php
/* Archiv-Template für den Slug "news", ausgewählt über die Template-Hierarchie */
get_header(); ?>

<div class="category-archive">
    <h1><?php single_cat_title(); ?></h1>
    
    <?php if (have_posts()) : ?>
        <div class="posts-grid">
            <?php while (have_posts()) : the_post(); ?>
                <?php get_template_part('content', 'category'); ?>
            <?php endwhile; ?>
        </div>
        
        <?php the_posts_pagination(); ?>
    <?php else : ?>
        <p>Keine Beiträge in dieser Kategorie gefunden.</p>
    <?php endif; ?>
</div>

<?php get_footer(); ?>

#Kategoriebeiträge per AJAX nachladen

Für eine bessere Benutzererfahrung implementieren Sie AJAX-Laden. Zwei Details bringen viele ins Straucheln: ajaxurl ist nur im wp-admin definiert, im Frontend müssen Sie es also selbst mitgeben, und jede Anfrage braucht einen Nonce, um ein Sicherheits-Review zu bestehen.

Registrieren Sie das Skript und übergeben Sie ihm die admin-ajax-URL sowie einen Nonce:

function enqueue_category_loader() {
    wp_enqueue_script(
        'category-loader',
        get_theme_file_uri('/js/category-loader.js'),
        array('jquery'),
        '1.0',
        true
    );
    wp_localize_script('category-loader', 'catLoader', array(
        'ajaxurl' => admin_url('admin-ajax.php'),
        'nonce'   => wp_create_nonce('load_category_posts'),
    ));
}
add_action('wp_enqueue_scripts', 'enqueue_category_loader');

Die Frontend-Anfrage liest anschließend aus dem lokalisierten Objekt:

jQuery(document).ready(function($) {
    $('.load-more').on('click', function() {
        var button = $(this);

        $.ajax({
            url: catLoader.ajaxurl,
            type: 'POST',
            data: {
                action: 'load_category_posts',
                nonce: catLoader.nonce,
                category: button.data('category'),
                page: button.data('page')
            },
            success: function(response) {
                $('.posts-container').append(response);
                button.data('page', button.data('page') + 1);
            }
        });
    });
});

Registrieren Sie schließlich den Handler für angemeldete und anonyme Besucher (wp_ajax_ und wp_ajax_nopriv_), prüfen Sie den Nonce und geben Sie das gerenderte Markup zurück:

function load_category_posts_handler() {
    check_ajax_referer('load_category_posts', 'nonce');

    $category = sanitize_text_field($_POST['category'] ?? '');
    $page     = max(1, intval($_POST['page'] ?? 1));

    $query = new WP_Query(array(
        'category_name'  => $category,
        'posts_per_page' => 5,
        'paged'          => $page,
    ));

    if ($query->have_posts()) {
        while ($query->have_posts()) {
            $query->the_post();
            printf(
                '<article><h3><a href="%s">%s</a></h3></article>',
                esc_url(get_permalink()),
                esc_html(get_the_title())
            );
        }
        wp_reset_postdata();
    }

    wp_die(); // required so admin-ajax stops cleanly
}
add_action('wp_ajax_load_category_posts', 'load_category_posts_handler');
add_action('wp_ajax_nopriv_load_category_posts', 'load_category_posts_handler');

#Kategoriebeiträge in einem Block-Theme anzeigen

Bei Block-Themes (Standard-Theme-Typ, seit Twenty Twenty-Two mit WordPress 5.9 erschien) brauchen Sie oft gar kein PHP. Der nach Kategorie gefilterte Query-Loop-Block gibt dieselbe Liste direkt aus dem Editor aus: Query-Loop einfügen, die Blockeinstellungen öffnen und unter Filter die gewünschte Kategorie hinzufügen. Speichern Sie das Ganze als synchronisiertes Muster, dann können Redakteure die kuratierte Liste ohne Eingriff ins Template auf jeder Seite platzieren, ein Ablauf, der sich in Redaktionsteams bewährt hat.

Der Kategoriefilter des Blocks trifft nur die ausgewählten Terme. Der Core wandelt ihn in eine Tax Query mit include_children auf false um, eine ausgewählte Elternkategorie zieht also keine Beiträge nach, die nur in ihren Unterkategorien liegen; nehmen Sie die Unterkategorien zusätzlich in den Filter auf.

Greifen Sie zu den Code-Ansätzen weiter oben, wenn Sie Logik brauchen, die der Block nicht ausdrücken kann: Transient-Caching, bedingte Ausschlüsse pro Archiv oder eine Ausgabe, die etwas anderes als das Theme verarbeitet (ein E-Mail-Newsletter, eine REST-Antwort).

#Kategoriebeiträge über die REST-API abrufen

Für Headless-Frontends, eine React-Insel oder eine externe Integration stellt WordPress Kategoriebeiträge über die REST-API bereit, ganz ohne eigenen Endpunkt:

GET /wp-json/wp/v2/posts?categories=5&per_page=10&_fields=id,title,link,excerpt

Nutzen Sie categories_exclude, um einen Term herauszufiltern, _embed, um Beitragsbilder und Term-Namen in einem Aufruf mitzuladen, und _fields, um die Nutzlast auf das zu reduzieren, was der Client tatsächlich rendert. Um einen Slug in die vom Endpunkt erwartete ID aufzulösen, fragen Sie zuerst /wp-json/wp/v2/categories?slug=news ab.

Drei Details aus dem REST-Handbuch entscheiden, ob eine Headless-Liste vollständig ist:

  • Unterkategorien brauchen die Objektform. categories=5 trifft nur den Term 5. Um seine Unterkategorien einzuschließen, senden Sie categories[terms]=5&categories[include_children]=true. Dasselbe Objekt akzeptiert categories[operator]=AND, wenn ein Beitrag alle genannten Terme tragen muss.
  • Eine Seite liefert höchstens 100 Einträge. Der Paginierungsleitfaden begrenzt per_page auf Werte von 1 bis 100. Lesen Sie die Antwort-Header X-WP-Total und X-WP-TotalPages aus und fordern Sie page=2, page=3 an, bis alles da ist.
  • _fields versteht verschachtelte Schlüssel. Seit WordPress 5.3 akzeptiert der Parameter _fields Pfade wie meta.event_datum, eine Liste kann also einen registrierten Meta-Schlüssel ohne das ganze Meta-Objekt anfordern. WordPress berechnet die nicht angeforderten Felder dann gar nicht, was auch die Antwortzeit verkürzt.

#Eine Kategorieabfrage debuggen, die die falschen Beiträge liefert

Wenn eine Abfrage zu viele, zu wenige oder unerwartete Beiträge liefert, sehen Sie sich das tatsächlich ausgeführte SQL an, statt bei den Argumenten zu raten. Installieren Sie Query Monitor, und das Tool zeigt jede Abfrage der Seite, einschließlich der von Ihrer Schleife erzeugten, wobei die langsamen markiert werden. Für eine schnelle Prüfung ohne Plugin geben Sie die geparste Abfrage aus:

$query = new WP_Query($args);
// The exact SQL WordPress built from your $args
error_log($query->request);

Hinter den meisten Überraschungen stecken zwei Ursachen: die Einbindung untergeordneter Terms (siehe include_children oben) und ein verirrter pre_get_posts-Filter aus einem Plugin oder dem Theme, der die Hauptabfrage verändert. Sieht das SQL korrekt aus, das Ergebnis ist aber leer, prüfen Sie, ob dem Term im aktuellen Sprach- oder Kontextbereich tatsächlich veröffentlichte Beiträge zugeordnet sind.

#Beiträge einer Kategorie mit WP-CLI auflisten

Für Audits, Migrationen und einmalige Exporte führt wp post list dasselbe WP_Query auf der Kommandozeile aus. Jede Option --<feld>=<wert> geht als Argument an WP_Query, die Kategorie-Regeln aus der Tabelle oben gelten also unverändert:

# Term-ID und Beitragszahl jeder Kategorie
wp term list category --fields=term_id,name,slug,count

# Veröffentlichte Beiträge in "nachrichten" und ihren Unterkategorien als CSV
wp post list --category_name=nachrichten --post_status=publish --fields=ID,post_title,post_date --format=csv

# Nur IDs, Beiträge direkt in Kategorie 12 (ohne Unterkategorien)
wp post list --category__in=12 --post_status=publish --format=ids

# Wie viele Beiträge ein Template für Kategorie 12 samt Unterkategorien zeigt
wp post list --cat=12 --post_status=publish --format=count

Zwei Standardwerte weichen von einer Template-Schleife ab. Der Quellcode des Befehls setzt posts_per_page auf -1 und post_status auf any, ohne --post_status=publish enthält die Ausgabe also auch Entwürfe, ausstehende und private Beiträge. Die Standardspalten sind ID, post_title, post_name, post_date und post_status, und --format akzeptiert table, csv, ids, json, count und yaml. Ein Vergleich von --format=count für --cat und --category__in mit derselben ID zeigt schnell, wie viele Beiträge nur in Unterkategorien liegen.

#Häufige Fehler bei WP_Query mit Kategorien

  1. Fehlender Post-Data-Reset: Rufen Sie nach benutzerdefinierten Schleifen immer wp_reset_postdata() auf
  2. Abfragen bei jedem Seitenaufruf: Verwenden Sie Caching für aufwändige Abfragen
  3. Fehlende Existenzpruefung: Prüfen Sie immer have_posts() vor der Schleife
  4. Falsche Modifikation der Hauptabfrage: Verwenden Sie pre_get_posts statt neuer Abfragen auf Archivseiten
  5. Pagination ignorieren: Denken Sie an die Seitennavigation für große Kategoriearchive

#Fazit

WordPress bietet mehrere Möglichkeiten, Beiträge aus Kategorien abzurufen, die jeweils für unterschiedliche Szenarien geeignet sind:

  • WP_Query: beste Wahl für komplexe, benutzerdefinierte Anzeigen
  • get_posts(): ideal für einfache Beitraegslisten
  • Shortcodes: perfekt für Flexibilität der Content-Editoren
  • pre_get_posts: unverzichtbar für die Modifikation von Archivseiten

Das Verständnis dieser Methoden und der richtige Einsatz jeder einzelnen macht Sie zu einem effektiveren WordPress-Entwickler. Denken Sie immer an die Leistung, besonders auf Websites mit vielen Inhalten.

Implementieren Sie auf Produktionsseiten Caching-Strategien und testen Sie Ihre Abfragen mit Tools wie Query Monitor, um optimale Leistung sicherzustellen.

Nächster Schritt

Machen Sie aus dem Artikel eine echte Umsetzung

Dieser Block stärkt die interne Verlinkung und führt Nutzer gezielt zum nächsten sinnvollen Schritt im Service- und Content-System.

Soll das Thema auf Ihrer Website umgesetzt werden?

Wenn Sie aus dem Artikel konkrete Maßnahmen für Website, Relaunch oder Weiterentwicklung ableiten wollen, definiere ich den Scope und setze ihn um.

Relevanter Cluster

Weitere WordPress-Dienste und Wissensbasis entdecken

Stärken Sie Ihr Unternehmen mit professionellem technischen Support in den Kernbereichen des WordPress-Ökosystems.

Muss ich ein erfahrener Entwickler sein, um diese Anleitung zu verwenden?#
Diese Anleitung richtet sich an WordPress-Entwickler mit mittlerem Kenntnisstand. Grundkenntnisse in PHP und WordPress werden vorausgesetzt, aber der gesamte Code wird Schritt für Schritt erklärt.
Funktionieren diese Techniken mit jedem WordPress-Theme?#
Die meisten Techniken sind theme-unabhängig und funktionieren mit Standard-WordPress-Themes. Stark angepasste Themes können jedoch zusätzliche Anpassungen erfordern.
Ist es sicher, diese Änderungen auf einer Live-Website umzusetzen?#
Die eigenen Schleifen aus Methode 1 bis 3 bleiben lokal, sie erzeugen eine eigene WP_Query und schließen mit wp_reset_postdata() ab. Heikel ist Methode 4, denn pre_get_posts greift in jedes Archiv ein, deshalb müssen die Prüfungen is_main_query() und !is_admin() stehen bleiben. Denken Sie zusätzlich an das Transient-Beispiel mit HOUR_IN_SECONDS, das eine Änderung bis zu eine Stunde lang verdeckt, und prüfen Sie das Ergebnis mit Query Monitor.
Funktionieren diese Methoden mit Page-Buildern wie Elementor?#
Der Shortcode aus Methode 3 funktioniert überall, Page-Builder geben ihn in einem Text- oder Shortcode-Widget aus und er nimmt die Attribute category und posts ohne weitere Integration entgegen. Der Query-Loop-Block gehört zum Block-Editor und steht auf einer Builder-Leinwand nicht zur Verfügung. Baut der Builder die Liste im Browser auf, holen Sie die Beiträge über /wp-json/wp/v2/posts?categories=5&_fields=id,title,link statt über eine PHP-Schleife.
Brauche ich in einem Block-Theme überhaupt noch Code?#
Für eine einfache Liste nicht. Der nach Kategorie gefilterte Query-Loop-Block gibt die Kategoriebeiträge direkt aus dem Editor aus. Greifen Sie zu den Code-Ansätzen, wenn Sie Caching, bedingte Ausschlüsse oder eine Ausgabe außerhalb des Themes benötigen, etwa eine REST-Antwort.

Sie brauchen ein FAQ für Branche und Zielmarkt? Wir erstellen eine Version passend zu Ihren Business-Zielen.

Kontakt aufnehmen

Ähnliche Artikel