Einfuehrung in das kategoriebasierte Abrufen von Beiträgen
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 moechten: Effizientes Abfragen von Beiträgen nach Kategorie ist für jeden WordPress-Entwickler unverzichtbar.
Dieser umfassende Leitfaden behandelt mehrere Ansaetze 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.
WordPress-Kategorien verstehen
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 angehoeren
- 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 Verstaendnis dieser Struktur hilft dabei, effizientere Abfragen zu schreiben und Probleme zu loesen.
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, loesen 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 aufgeloeste 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, die auf einem stark frequentierten Shop schnell sichtbar wird.
Methode 1: WP_Query (der flexible Ansatz)
WP_Query ist die primäre WordPress-Klasse für das Abfragen von Beiträgen. Sie bietet maximale Flexibilitaet und ist der empfohlene Ansatz für die meisten Anwendungsfaelle.
Grundlegende Kategorieabfrage
$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);
Mehrere Kategorien
// 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 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
Methode 2: get_posts() (der einfache Ansatz)
Für einfachere Anwendungsfaelle bietet get_posts() eine unkompliziertere API.
Grundlegende Verwendung
$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();
Mit Kategoriename
$posts = get_posts(array(
'category_name' => 'technology',
'numberposts' => 5
));
Methode 3: Shortcodes für Content-Editoren
Das Erstellen eines Shortcodes ermöglicht es Content-Editoren, Kategorie-Beitraegslisten überall einzufuegen.
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"]
Methode 4: Die Hauptabfrage modifizieren
Wenn Sie ändern moechten, 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');
Methode 5: tax_query für präzises, taxonomiebewusstes Filtern
Die Abkuerzungen cat und category_name sind bequem, aber tax_query ist das Argument der Wahl, sobald die Anforderungen konkret werden: Kategorien mit Schlagwoertern kombinieren, Unterkategorien ausschließen oder eine eigene Taxonomie abfragen. Außerdem druecken Sie damit UND/ODER-Logik ausdruecklich 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 Schluessel include_children ist das praktische Detail, das die meisten übersehen. Standardmaeßig zieht eine category-tax_query jeden untergeordneten Term mit hinein, was für ein Archiv meist erwuenscht 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. Bei einem WooCommerce-Shop, wie er im deutschsprachigen Handel verbreitet ist, ist das genau der Hebel, um etwa Produktkategorien sauber von den regulaeren Beitragskategorien zu trennen.
Leistungsoptimierung
1. Transients für aufwaendige 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);
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.
Fortgeschrittene Techniken
Benutzerdefinierte Templates für Kategoriearchive
Erstellen Sie eine Template-Datei category-news.php für kategoriespezifisches Styling:
<?php
/* Template Name: Kategorie - Neuigkeiten */
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(); ?>
AJAX-Laden für Kategoriebeiträge
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 seit WordPress 6.1) brauchen Sie oft gar kein PHP. Der nach Kategorie gefilterte Query-Loop-Block gibt dieselbe Liste direkt aus dem Editor aus: Query-Loop einfuegen, die Blockeinstellungen oeffnen und unter Filter die gewuenschte Kategorie hinzufuegen. 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 bewaehrt hat.
Greifen Sie zu den Code-Ansaetzen weiter oben, wenn Sie Logik brauchen, die der Block nicht ausdruecken kann: Transient-Caching, bedingte Ausschluesse 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 tatsaechlich rendert. Um einen Slug in die vom Endpunkt erwartete ID aufzuloesen, fragen Sie zuerst /wp-json/wp/v2/categories?slug=news ab.
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 tatsaechlich ausgefuehrte 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 Pruefung 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 veraendert. Sieht das SQL korrekt aus, das Ergebnis ist aber leer, prüfen Sie, ob dem Term im aktuellen Sprach- oder Kontextbereich tatsaechlich veroeffentlichte Beiträge zugeordnet sind.
Häufige Fehler vermeiden
- Fehlender Post-Data-Reset: Rufen Sie nach benutzerdefinierten Schleifen immer
wp_reset_postdata()auf - Abfragen bei jedem Seitenaufruf: Verwenden Sie Caching für aufwaendige Abfragen
- Fehlende Existenzpruefung: Pruefen 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 Flexibilitaet der Content-Editoren
- pre_get_posts: unverzichtbar für die Modifikation von Archivseiten
Das Verstaendnis 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.







