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_termsundwp_term_taxonomygespeichert - Beitrag-Kategorie-Beziehungen werden in
wp_term_relationshipsgespeichert
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 wirdKategorie-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:
| Schnittstelle | Argument | Beiträge aus Unterkategorien |
|---|---|---|
| WP_Query | cat | enthalten |
| WP_Query | category_name | enthalten |
| WP_Query | category__in, category__and, category__not_in | nicht enthalten |
| WP_Query | tax_query | enthalten, außer include_children ist false |
| get_posts() | category | enthalten (Alias von cat) |
| REST-API | categories=5 | nicht enthalten |
| REST-API | categories[terms]=5&categories[include_children]=true | enthalten |
| Query-Loop-Block | Kategoriefilter | nicht enthalten |
| WP-CLI | --cat, --category_name | enthalten (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:
numberpostssteht standardmäßig auf 5, ein Aufruf ohne Limit liefert also stillschweigend fünf Beiträge.post_statussteht aufpublishundsuppress_filtersauftrue, daher laufenposts_whereund ähnliche SQL-Filter von Plugins nicht. Die Actionpre_get_postsfeuert trotzdem.ignore_sticky_postsundno_found_rowswerden immer auftruegezwungen. Eine nummerierte Paginierung lässt sich aufget_posts()nicht aufbauen, weil die Gesamtzahl nie berechnet wird.includesetztposts_per_pageauf 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,excerptNutzen 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=5trifft nur den Term 5. Um seine Unterkategorien einzuschließen, senden Siecategories[terms]=5&categories[include_children]=true. Dasselbe Objekt akzeptiertcategories[operator]=AND, wenn ein Beitrag alle genannten Terme tragen muss. - Eine Seite liefert höchstens 100 Einträge. Der Paginierungsleitfaden begrenzt
per_pageauf Werte von 1 bis 100. Lesen Sie die Antwort-HeaderX-WP-TotalundX-WP-TotalPagesaus und fordern Siepage=2,page=3an, bis alles da ist. _fieldsversteht verschachtelte Schlüssel. Seit WordPress 5.3 akzeptiert der Parameter_fieldsPfade wiemeta.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=countZwei 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
- Fehlender Post-Data-Reset: Rufen Sie nach benutzerdefinierten Schleifen immer
wp_reset_postdata()auf - Abfragen bei jedem Seitenaufruf: Verwenden Sie Caching für aufwändige Abfragen
- Fehlende Existenzpruefung: Prüfen Sie immer
have_posts()vor der Schleife - Falsche Modifikation der Hauptabfrage: Verwenden Sie
pre_get_postsstatt neuer Abfragen auf Archivseiten - 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.







