Eine der häufigsten Aufgaben für WordPress-Entwickler ist das Anzeigen einer Liste von Beiträgen aus einer bestimmten Kategorie. Ob Sie einen Nachrichtenbereich, eine Blogseite mit thematischen Beiträgen oder ein Portfolio erstellen möchten – die Fähigkeit, Inhalte aus bestimmten Kategorien zu filtern und abzurufen, ist grundlegend wichtig. WordPress bietet mehrere robuste Methoden, um dies zu erreichen, von einfachen Funktionsaufrufen bis hin zu komplexen Datenbankabfragen. In diesem umfassenden Leitfaden werden wir alle diese Methoden im Detail untersuchen, mit Fokus auf Best Practices, Optimierung und häufige Fehler, auf die Entwickler stoßen.
Es gibt drei Hauptmethoden zum Abrufen von Beiträgen aus Kategorien in WordPress: get_posts() für einfache Listen ohne vollständige Schleifensteuerung, WP_Query für volle Kontrolle mit Paginierung und erweiterten Filtern, sowie query_posts(), das generell nicht empfohlen wird, da es die Hauptschleife beeinträchtigt. Wir werden jede Methode im Detail durchgehen, mit praktischen Codebeispielen, die Sie direkt in Ihren eigenen Projekten verwenden können.
Einführung in WordPress-Taxonomien und Kategorien
Bevor wir uns in die Codebeispiele vertiefen, ist es wichtig, die grundlegenden Konzepte hinter dem Kategoriensystem in WordPress zu verstehen. Kategorien sind eine Art von Taxonomie, eine Möglichkeit, Inhalte in WordPress zu organisieren. Die Standardtaxonomien umfassen Kategorien für Beiträge und Tags, aber Sie können auch benutzerdefinierte Taxonomien für komplexere Inhaltsstrukturen erstellen. Eine Kategorie in WordPress ist hierarchisch, was bedeutet, dass Sie Unterkategorien haben können, die wiederum eigene Unterkategorien haben können. Diese Hierarchie ist wichtig zu berücksichtigen, wenn Sie Beiträge abrufen möchten, da Sie entscheiden müssen, ob Sie nur Beiträge aus einer bestimmten Kategorie oder auch Beiträge aus deren Unterkategorien anzeigen möchten.
Wenn Sie mit Kategorien in WordPress arbeiten, werden Sie häufig auf die Begriffe „Category ID” und „Category Slug” stoßen. Die Category ID ist eine eindeutige Identifikationsnummer, die WordPress jeder Kategorie zuordnet, während der Category Slug eine URL-freundliche Zeichenfolge ist, die die Kategorie identifiziert. Beide können zum Filtern von Beiträgen verwendet werden, haben aber unterschiedliche Vor- und Nachteile. Die Category ID ist genauer, da sie eindeutig ist, während der Category Slug lesbarer ist und ohne größere Auswirkungen auf bestehende Links geändert werden kann. Es wird empfohlen, den Category Slug zu verwenden, wo immer dies praktisch möglich ist, da dies den Code wartungsfreundlicher macht.
Methode 1: get_posts() – Schnell und Einfach
Die Funktion get_posts() ist der einfachste Weg, Beiträge aus einer Kategorie abzurufen, und eignet sich perfekt für Situationen, in denen Sie eine einfache Liste ohne erweiterte Schleifensteuerung benötigen. Diese Funktion gibt ein Array von Beitragsobjekten zurück, über das Sie dann iterieren können. Ein Vorteil von get_posts() ist, dass es die Hauptschleife in WordPress nicht beeinflusst, was bedeutet, dass Sie es sicher in der Seitenleiste, im Footer oder anderen Teilen der Seite verwenden können, ohne das Hauptinhalt zu stören.
<?php
$args = array(
'posts_per_page' => 5,
'category_name' => 'nachrichten',
'orderby' => 'date',
'order' => 'DESC',
'suppress_filters' => true,
);
$posts_array = get_posts( $args );
foreach ( $posts_array as $post ) :
setup_postdata( $post );
?>
<li>
<a href="<?php the_permalink(); ?>">
<?php the_title(); ?>
</a>
<span class="post-date"><?php echo get_the_date(); ?></span>
</li>
<?php endforeach;
wp_reset_postdata();
?>
Dieses Beispiel zeigt die grundlegenden Parameter, die Sie häufig verwenden werden: posts_per_page bestimmt, wie viele Beiträge abgerufen werden sollen, category_name filtert nach dem Kategorie-Slug, und orderby und order steuern die Sortierung. Beachten Sie, dass wir setup_postdata() verwenden, um globale Beitragdaten für jeden Beitrag in der Schleife einzurichten, und wp_reset_postdata() verwenden, um diese Daten zurückzusetzen, nachdem die Schleife abgeschlossen ist. Dies ist entscheidend, um zu verhindern, dass spätere Funktionsaufrufe falsche Beitragdaten verwenden.
Um Beiträge aus einer bestimmten Kategorie mit der Category ID anstelle des Slugs abzurufen, können Sie den cat-Parameter verwenden:
<?php
$args = array(
'posts_per_page' => 10,
'cat' => 12, // Kategorie-ID
'orderby' => 'title',
'order' => 'ASC',
);
$posts = get_posts( $args );
foreach ( $posts as $post ) {
setup_postdata( $post );
echo '<h3>' . get_the_title() . '</h3>';
echo '<p>' . get_the_excerpt() . '</p>';
}
wp_reset_postdata();
?>
Methode 2: WP_Query – Volle Kontrolle mit Paginierung
Für fortgeschrittene Anwendungsfälle, in denen Sie Paginierung, komplexe Filter oder vollen Zugriff auf alle WordPress-Schleifenfunktionen benötigen, ist WP_Query die beste Wahl. Diese Klasse gibt Ihnen viel mehr Kontrolle über die Abfrage und ermöglicht es Ihnen, komplexe Ansichten zu erstellen, die mit get_posts() fast unmöglich wären. WP_Query ist auch die am besten dokumentierte und flexibelste Methode für benutzerdefinierte Templates.
<?php
$category_query = new WP_Query( array(
'category__in' => array( 12, 15, 18 ),
'posts_per_page' => 6,
'ignore_sticky_posts' => true,
'paged' => get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1,
) );
if ( $category_query->have_posts() ) :
echo '<div class="posts-grid">';
while ( $category_query->have_posts() ) :
$category_query->the_post();
?>
<article class="post-item">
<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
<div class="post-meta">
<span class="date"><?php echo get_the_date(); ?></span>
<span class="author"><?php echo get_the_author(); ?></span>
</div>
<div class="post-excerpt">
<?php the_excerpt(); ?>
</div>
<a href="<?php the_permalink(); ?>" class="read-more">
Weiterlesen
</a>
</article>
<?php
endwhile;
echo '</div>';
// Paginierung
echo '<div class="pagination">';
echo paginate_links( array(
'total' => $category_query->max_num_pages,
'current' => max( 1, get_query_var( 'paged' ) ),
'prev_text' => __( '« Zurück' ),
'next_text' => __( 'Weiter »' ),
) );
echo '</div>';
wp_reset_postdata();
endif;
?>
Dieses Beispiel demonstriert mehrere erweiterte Funktionen. Der Parameter category__in ermöglicht es Ihnen, mehrere Kategorie-IDs als Array anzugeben, was bedeutet, dass Beiträge aus allen aufgeführten Kategorien einbezogen werden. ignore_sticky_posts stellt sicher, dass angeheftete Beiträge keine spezielle Behandlung erhalten, es sei denn, Sie wünschen dies explizit. Der Parameter paged ruft die aktuelle Seite aus der URL ab, was für die Paginierung wesentlich ist.
Für eine präzisere Kontrolle können Sie category__and verwenden, wenn Sie nur Beiträge haben möchten, die ALLEN angegebenen Kategorien angehören, nicht nur einer davon:
<?php
$args = array(
'category__and' => array( 12, 15 ),
'posts_per_page' => 10,
'orderby' => 'comment_count',
'order' => 'DESC',
);
$query = new WP_Query( $args );
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
// Inhalt anzeigen
}
wp_reset_postdata();
}
?>
Unterkategorien in Abfragen einbeziehen
Eine häufige Frage von Entwicklern ist, wie man Unterkategorien einbezieht, wenn man eine übergeordnete Kategorie abfragt. Das Standardverhalten von WordPress ist, dass category_name oder cat nur die spezifische Kategorie abgleicht, nicht deren Unterkategorien. Um Unterkategorien einzubeziehen, müssen Sie entweder category__in mit allen relevanten Kategorie-IDs verwenden oder eine tax_query hinzufügen, die Unterkategorien explizit einbezieht.
Hier ist eine robuste Lösung, die automatisch alle Unterkategorien abruft:
<?php
function get_category_with_children( $category_slug ) {
$category = get_category_by_slug( $category_slug );
if ( ! $category ) {
return array();
}
$args = array(
'taxonomy' => 'category',
'child_of' => $category->term_id,
'hide_empty' => true,
);
$child_categories = get_categories( $args );
$category_ids = array( $category->term_id );
foreach ( $child_categories as $child ) {
$category_ids[] = $child->term_id;
}
return $category_ids;
}
// In WP_Query verwenden
$parent_slug = 'produkte';
$category_ids = get_category_with_children( $parent_slug );
$args = array(
'category__in' => $category_ids,
'posts_per_page' => 12,
'orderby' => 'date',
'order' => 'DESC',
);
$products_query = new WP_Query( $args );
if ( $products_query->have_posts() ) {
while ( $products_query->have_posts() ) {
$products_query->the_post();
// Produkte anzeigen
}
wp_reset_postdata();
}
?>
Diese Funktion get_category_with_children() nimmt einen übergeordneten Kategorie-Slug, findet alle seine Unterkategorien und gibt ein Array aller relevanten Kategorie-IDs zurück, die Sie in WP_Query verwenden können. Dies ist besonders nützlich für Websites mit komplexen Inhaltshierarchien, bei denen alle verwandten Kategorien gemeinsam angezeigt werden sollen.
Kategorien aus Abfragen ausschließen
Ebenso wichtig wie das Einschließen bestimmter Kategorien ist das Ausschließen anderer. WordPress bietet den Parameter category__not_in für diesen Zweck. Dies ist nützlich für Situationen, in denen Sie alle Beiträge ANZEIGEN MÖCHTEN, AUSSER diejenigen, die einer bestimmten Kategorie angehören, beispielsweise um eine „Featured der Woche”-Kategorie von der Hauptliste auszuschließen.
<?php
$args = array(
'post_type' => 'post',
'posts_per_page' => 10,
'category__not_in' => array( 25, 30 ), // Diese Kategorie-IDs ausschließen
'post_status' => 'publish',
'ignore_sticky_posts' => true,
);
$main_query = new WP_Query( $args );
if ( $main_query->have_posts() ) {
while ( $main_query->have_posts() ) {
$main_query->the_post();
// Beitrag anzeigen
}
wp_reset_postdata();
}
?>
Ein häufiger Anwendungsfall ist das Ausschließen einer Kategorie von der Startseite:
<?php
if ( is_front_page() ) {
$args = array(
'posts_per_page' => 5,
'category__not_in' => array( get_cat_ID( 'featured' ) ),
);
} else {
$args = array(
'posts_per_page' => 10,
);
}
$query = new WP_Query( $args );
?>
Benutzerdefinierte Taxonomien
Viele WordPress-Installationen verwenden benutzerdefinierte Taxonomien zusätzlich zu Standardkategorien. Beispielsweise könnte eine Website für Bücher eine „Genre”-Taxonomie haben, die ähnlich wie Kategorien funktioniert. Um Beiträge basierend auf benutzerdefinierten Taxonomien abzufragen, müssen Sie den tax_query-Parameter anstelle der regulären Category-Parameter verwenden.
<?php
$args = array(
'post_type' => 'buch',
'posts_per_page' => 12,
'tax_query' => array(
array(
'taxonomy' => 'genre',
'field' => 'slug',
'terms' => 'thriller',
'operator' => 'IN',
),
),
);
$thriller_books = new WP_Query( $args );
if ( $thriller_books->have_posts() ) {
while ( $thriller_books->have_posts() ) {
$thriller_books->the_post();
// Bücher anzeigen
}
wp_reset_postdata();
}
?>
Sie können auch mehrere Taxonomieabfragen mit AND- oder OR-Operatoren kombinieren:
<?php
$args = array(
'post_type' => 'buch',
'posts_per_page' => 20,
'tax_query' => array(
'relation' => 'AND',
array(
'taxonomy' => 'genre',
'field' => 'slug',
'terms' => array( 'thriller', 'krimi' ),
),
array(
'taxonomy' => 'autor',
'field' => 'name',
'terms' => array( 'Jo Nesbø' ),
'operator' => 'NOT IN',
),
),
);
$query = new WP_Query( $args );
?>
Leistungsoptimierung
Datenbankabfragen können eine erhebliche Quelle für langsame Ladezeiten auf WordPress-Websites sein, insbesondere wenn Sie viele Beiträge oder komplexe Filter haben. Glücklicherweise gibt es mehrere Techniken, die Sie verwenden können, um Ihre Abfragen zu optimieren und die Belastung der Datenbank zu reduzieren.
Die erste und wichtigste Optimierung besteht darin, zu begrenzen, welche Daten aus der Datenbank abgerufen werden. WordPress ruft standardmäßig alle Beitragsfelder ab, einschließlich Inhalt, Auszüge und aller Metaboxen. Wenn Sie nur Titel und Permalinks benötigen, können Sie Zeit sparen, indem Sie nur diese Felder anfordern:
<?php
$args = array(
'category_name' => 'nachrichten',
'posts_per_page' => 5,
'fields' => 'ids', // Nur Beitrag-IDs
'no_found_rows' => true, // Gesamtzahl der Zeilen nicht zählen
);
$post_ids = get_posts( $args );
foreach ( $post_ids as $id ) {
$title = get_the_title( $id );
$link = get_permalink( $id );
echo '<li><a href="' . esc_url( $link ) . '">' . esc_html( $title ) . '</a></li>';
}
?>
'fields' => 'ids' teilt WordPress mit, dass Sie nur ein Array mit Beitrag-IDs anstelle vollständiger Beitragsobjekte wünschen. no_found_rows' => true deaktiviert die Zählung der Gesamtzahl der Zeilen, was sonst eine zusätzliche Datenbankabfrage erfordert. Dies ist besonders nützlich, wenn Sie keine Paginierung verwenden.
Für eine granulare Kontrolle können Sie angeben, welche Felder Sie abrufen möchten:
<?php
$args = array(
'category_name' => 'events',
'posts_per_page' => 10,
'fields' => array( 'ID', 'post_title', 'post_excerpt', 'post_date' ),
);
$posts = get_posts( $args );
foreach ( $posts as $post ) {
echo '<h3>' . esc_html( $post->post_title ) . '</h3>';
echo '<p>' . esc_html( $post->post_excerpt ) . '</p>';
echo '<time>' . esc_html( date_i18n( get_option( 'date_format' ), strtotime( $post->post_date ) ) ) . '</time>';
}
?>
Transient API für Caching verwenden
Für Abfragen, die sich nicht häufig ändern, können Sie die Leistung dramatisch verbessern, indem Sie die Ergebnisse mit der Transient API zwischenspeichern. Dies speichert die Abfrageergebnisse in der Datenbank (oder einem anderen Cache-Backend) für einen bestimmten Zeitraum, sodass Sie vermeiden, dieselbe Abfrage immer und immer wieder auszuführen.
<?php
function get_cached_category_posts( $category_slug, $posts_per_page = 5, $cache_time = HOUR_IN_SECONDS ) {
$cache_key = 'category_posts_' . $category_slug . '_' . $posts_per_page;
$cached_posts = get_transient( $cache_key );
if ( false !== $cached_posts ) {
return $cached_posts;
}
$args = array(
'category_name' => $category_slug,
'posts_per_page' => $posts_per_page,
'orderby' => 'date',
'order' => 'DESC',
);
$posts = get_posts( $args );
set_transient( $cache_key, $posts, $cache_time );
return $posts;
}
// Die gecachte Funktion verwenden
$latest_news = get_cached_category_posts( 'nachrichten', 5, 15 * MINUTE_IN_SECONDS );
foreach ( $latest_news as $post ) {
setup_postdata( $post );
echo '<div class="news-item">';
the_title( '<h3>', '</h3>' );
the_excerpt();
echo '</div>';
}
wp_reset_postdata();
?>
Diese Funktion prüft zunächst, ob eine zwischengespeicherte Version der Abfrageergebnisse vorhanden ist. Falls ja, werden sie sofort zurückgegeben, ohne eine neue Abfrage auszuführen. Falls nicht, wird die Abfrage ausgeführt, die Ergebnisse werden mit set_transient() zwischengespeichert und dann zurückgegeben. Der cache_time-Parameter bestimmt, wie lange die Ergebnisse gültig sind – in diesem Beispiel 15 Minuten.
Für fortgeschrittenes Caching, das automatisch invalidiert wird, wenn neue Beiträge veröffentlicht werden, können Sie Hooks hinzufügen:
<?php
function clear_category_posts_cache( $post_id ) {
// Nur cachen, wenn es ein veröffentlichter Beitrag ist
if ( get_post_status( $post_id ) !== 'publish' ) {
return;
}
$categories = get_the_category( $post_id );
foreach ( $categories as $category ) {
delete_transient( 'category_posts_' . $category->slug . '_5' );
delete_transient( 'category_posts_' . $category->slug . '_10' );
}
}
add_action( 'save_post', 'clear_category_posts_cache' );
add_action( 'delete_post', 'clear_category_posts_cache' );
?>
Shortcodes für Kategorieansichten erstellen
Eine der flexibelsten Möglichkeiten, Kategorieansichten zu implementieren, ist durch WordPress-Shortcodes. Dies ermöglicht es Redakteuren, Kategorielisten einfach zum Inhalt hinzuzufügen, ohne Code schreiben zu müssen.
<?php
function category_posts_shortcode( $atts ) {
$atts = shortcode_atts( array(
'category' => '',
'limit' => 5,
'orderby' => 'date',
'order' => 'DESC',
'show_date' => 'yes',
'show_excerpt' => 'yes',
'template' => 'default',
), $atts, 'kategorie_posts' );
if ( empty( $atts['category'] ) ) {
return '<p class="error">Bitte geben Sie eine Kategorie an.</p>';
}
$args = array(
'category_name' => $atts['category'],
'posts_per_page' => intval( $atts['limit'] ),
'orderby' => $atts['orderby'],
'order' => $atts['order'],
'ignore_sticky_posts' => true,
);
$posts = get_posts( $args );
if ( empty( $posts ) ) {
return '<p>Keine Beiträge in dieser Kategorie gefunden.</p>';
}
ob_start();
?>
<div class="category-posts category-posts--<?php echo esc_attr( $atts['template'] ); ?>">
<?php foreach ( $posts as $post ) :
setup_postdata( $post );
?>
<article class="category-post-item">
<h3 class="post-title">
<a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
</h3>
<?php if ( 'yes' === $atts['show_date'] ) : ?>
<time class="post-date" datetime="<?php echo esc_attr( get_the_date( 'c' ) ); ?>">
<?php echo esc_html( get_the_date() ); ?>
</time>
<?php endif; ?>
<?php if ( 'yes' === $atts['show_ex ?>
<div class="post-excerpt'] ) :cerpt">
<?php the_excerpt(); ?>
</div>
<?php endif; ?>
</article>
<?php endforeach;
wp_reset_postdata();
?>
</div>
<?php
return ob_get_clean();
}
add_shortcode( 'kategorie_posts', 'category_posts_shortcode' );
?>
Jetzt können Redakteure den Shortcode in ihrem Inhalt verwenden:
[kategorie_posts category="nachrichten" limit="5" orderby="date" show_date="yes"]
Für noch mehr Flexibilität können Sie Unterstützung für mehrere Kategorien hinzufügen:
<?php
function advanced_category_shortcode( $atts ) {
$atts = shortcode_atts( array(
'categories' => '',
'operator' => 'IN', // IN, AND, NOT IN
'limit' => 6,
'columns' => 2,
'show_thumb' => 'yes',
), $atts, 'kategorien' );
$categories = array_filter( array_map( 'trim', explode( ',', $atts['categories'] ) ) );
if ( empty( $categories ) ) {
return '<p class="shortcode-error">Bitte geben Sie mindestens eine Kategorie an.</p>';
}
$category_ids = array();
foreach ( $categories as $cat_slug ) {
$cat = get_category_by_slug( $cat_slug );
if ( $cat ) {
$category_ids[] = $cat->term_id;
}
}
if ( empty( $category_ids ) ) {
return '<p class="shortcode-error">Ungültige Kategorien angegeben.</p>';
}
$args = array(
'category__in' => $category_ids,
'posts_per_page' => intval( $atts['limit'] ),
'ignore_sticky_posts' => true,
);
if ( 'AND' === $atts['operator'] ) {
$args['category__and'] = $category_ids;
unset( $args['category__in'] );
}
$query = new WP_Query( $args );
ob_start();
?>
<div class="posts-grid columns-<?php echo esc_attr( $atts['columns'] ); ?>">
<?php if ( $query->have_posts() ) :
while ( $query->have_posts() ) : $query->the_post();
?>
<article class="post-card">
<?php if ( 'yes' === $atts['show_thumb'] && has_post_thumbnail() ) : ?>
<div class="post-thumbnail">
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail( 'medium', array( 'loading' => 'lazy' ) ); ?>
</a>
</div>
<?php endif; ?>
<div class="post-content">
<h3><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
<?php the_excerpt(); ?>
</div>
</article>
<?php
endwhile;
wp_reset_postdata();
endif; ?>
</div>
<?php
return ob_get_clean();
}
add_shortcode( 'kategorien', 'advanced_category_shortcode' );
?>
AJAX-Laden von Kategoriebeiträgen
Für große Websites mit vielen Beiträgen kann AJAX-Laden eine viel bessere Benutzererfahrung bieten, indem weitere Beiträge asynchron geladen werden, ohne die Seite neu zu laden. Dies ist besonders nützlich für „Mehr laden”-Funktionalität.
Zuerst registrieren Sie das JavaScript:
<?php
function enqueue_category_ajax_scripts() {
wp_enqueue_script(
'category-ajax',
get_template_directory_uri() . '/js/category-ajax.js',
array( 'jquery' ),
'1.0',
true
);
wp_localize_script( 'category-ajax', 'categoryAjax', array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'category_ajax_nonce' ),
) );
}
add_action( 'wp_enqueue_scripts', 'enqueue_category_ajax_scripts' );
?>
Dann erstellen Sie den AJAX-Handler:
<?php
function load_more_category_posts() {
check_ajax_referer( 'category_ajax_nonce', 'nonce' );
$page = isset( $_POST['page'] ) ? intval( $_POST['page'] ) : 1;
$category = isset( $_POST['category'] ) ? sanitize_text_field( $_POST['category'] ) : '';
$posts_per_page = isset( $_POST['posts_per_page'] ) ? intval( $_POST['posts_per_page'] ) : 6;
$args = array(
'category_name' => $category,
'posts_per_page' => $posts_per_page,
'paged' => $page,
'post_status' => 'publish',
);
$query = new WP_Query( $args );
if ( $query->have_posts() ) :
while ( $query->have_posts() ) : $query->the_post();
get_template_part( 'template-parts/post', 'card' );
endwhile;
wp_reset_postdata();
endif;
wp_die();
}
add_action( 'wp_ajax_load_category_posts', 'load_more_category_posts' );
add_action( 'wp_ajax_nopriv_load_category_posts', 'load_more_category_posts' );
?>
JavaScript für die Handhabung der „Mehr laden”-Schaltfläche:
jQuery(document).ready(function($) {
var currentPage = 1;
var isLoading = false;
var hasMore = true;
$('.load-more-category').on('click', function(e) {
e.preventDefault();
if (isLoading || !hasMore) return;
var $button = $(this);
var category = $button.data('category');
var postsPerPage = $button.data('posts-per-page') || 6;
isLoading = true;
$button.addClass('loading').text('Lädt...');
$.ajax({
url: categoryAjax.ajaxurl,
type: 'POST',
data: {
action: 'load_category_posts',
nonce: categoryAjax.nonce,
page: currentPage + 1,
category: category,
posts_per_page: postsPerPage
},
success: function(response) {
if (response.trim()) {
$('.posts-grid').append(response);
currentPage++;
} else {
hasMore = false;
$button.hide();
}
},
error: function() {
alert('Ein Fehler ist aufgetreten. Bitte versuchen Sie es erneut.');
},
complete: function() {
isLoading = false;
$button.removeClass('loading').text('Mehr laden');
}
});
});
});
Häufige Probleme und Lösungen
Selbst erfahrene WordPress-Entwickler stoßen regelmäßig auf Probleme bei der Arbeit mit Kategorieabfragen. Hier sind die häufigsten Probleme und ihre Lösungen.
Problem: Leere Ergebnisse, obwohl Beiträge vorhanden sind. Dies liegt oft daran, dass post_status nicht korrekt eingestellt ist. Standardmäßig zeigt WP_Query nur veröffentlichte Beiträge an, aber wenn Sie in einer Entwicklungsumgebung testen, können Beiträge den Status „Entwurf” oder „Ausstehend” haben.
<?php
// Alle veröffentlichten Beiträge anzeigen
$args = array(
'category_name' => 'nachrichten',
'post_status' => 'publish',
);
// Zum Testen: Alle Beiträge anzeigen, unabhängig vom Status
$test_args = array(
'category_name' => 'nachrichten',
'post_status' => array( 'publish', 'draft', 'pending', 'private' ),
);
?>
Problem: Beiträge werden mit falscher Kategorie angezeigt. Prüfen Sie, ob Sie den richtigen Parameter verwenden. category_name nimmt einen Kategorie-Slug (Zeichenfolge), während cat eine Kategorie-ID (ganze Zahl) nimmt. Ein häufiger Fehler ist, cat mit einer Zeichenfolge zu verwenden oder umgekehrt.
<?php
// Falsch - cat erwartet eine Zahl
$args = array( 'cat' => 'nachrichten' ); // Funktioniert nicht!
// Richtig - category_name nimmt eine Zeichenfolge
$args = array( 'category_name' => 'nachrichten' );
// Richtig - cat nimmt eine Zahl
$args = array( 'cat' => 42 ); // Angenommen, 42 ist eine gültige Kategorie-ID
// Kategorie-ID zuerst prüfen
$category = get_category_by_slug( 'nachrichten' );
if ( $category ) {
$args = array( 'cat' => $category->term_id );
}
?>
Problem: Angeheftete Beiträge werden zuerst angezeigt. Das Standardverhalten von WordPress ist, angeheftete Beiträge vor den Ergebnissen anzuzeigen. Wenn Sie eine chronologische Liste ohne diese Priorisierung wünschen, müssen Sie dies explizit deaktivieren.
<?php
$args = array(
'category_name' => 'nachrichten',
'ignore_sticky_posts' => true, // Angeheftete Beiträge ignorieren
'posts_per_page' => 10,
);
// Alternative: Angeheftete Beiträge einbeziehen, aber alle nach Datum sortieren
$args = array(
'category_name' => 'nachrichten',
'post__in' => get_option( 'sticky_posts' ),
'posts_per_page' => 10,
'orderby' => 'date',
'order' => 'DESC',
);
?>
Problem: Paginierung funktioniert nicht. Dies ist ein sehr häufiges Problem, das oft auf eine fehlerhafte Konfiguration des paged-Parameters zurückzuführen ist oder dass WP_Query nicht korrekt mit der Hauptschleife verwendet wird.
<?php
// Korrekte Paginierung in WP_Query
$paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
$args = array(
'category_name' => 'nachrichten',
'posts_per_page' => 10,
'paged' => $paged,
);
$query = new WP_Query( $args );
if ( $query->have_posts() ) :
while ( $query->have_posts() ) : $query->the_post();
// Beitrag anzeigen
endwhile;
// Paginierung
echo paginate_links( array(
'total' => $query->max_num_pages,
'current' => $paged,
) );
wp_reset_postdata();
endif;
?>
Benutzerdefinierte Templates für Kategorieansichten
WordPress ermöglicht es Ihnen, benutzerdefinierte Templates für bestimmte Kategorien zu erstellen, was Ihnen die volle Kontrolle darüber gibt, wie Beiträge aus verschiedenen Kategorien angezeigt werden.
Erstellen Sie eine Datei in Ihrem Theme-Ordner mit dem Namen category-{slug}.php, wobei {slug} der Kategorie-Slug ist. Beispielsweise erstellen Sie für die Kategorie „nachrichten” die Datei category-nachrichten.php. In dieser Datei können Sie eine vollständig angepasste Ansicht erstellen:
<?php
/**
* Template Name: Nachrichten Kategorie
* Description: Benutzerdefiniertes Template für die „nachrichten"-Kategorie
*/
get_header();
$category = get_category_by_slug( 'nachrichten' );
?>
<div class="news-archive">
<header class="archive-header">
<h1><?php echo esc_html( $category->name ); ?></h1>
<?php if ( category_description( $category->term_id ) ) : ?>
<div class="archive-description">
<?php echo wp_kses_post( category_description( $category->term_id ) ); ?>
</div>
<?php endif; ?>
</header>
<div class="news-grid">
<?php
$news_args = array(
'cat' => $category->term_id,
'posts_per_page' => 12,
'paged' => get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1,
);
$news_query = new WP_Query( $news_args );
if ( $news_query->have_posts() ) :
while ( $news_query->have_posts() ) : $news_query->the_post();
?>
<article class="news-item">
<?php if ( has_post_thumbnail() ) : ?>
<div class="news-thumbnail">
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail( 'medium_large', array( 'loading' => 'lazy' ) ); ?>
</a>
</div>
<?php endif; ?>
<div class="news-content">
<span class="news-date"><?php echo get_the_date(); ?></span>
<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
<?php the_excerpt(); ?>
</div>
</article>
<?php
endwhile;
wp_reset_postdata();
else :
?>
<p class="no-news">Keine Nachrichten gefunden.</p>
<?php endif; ?>
</div>
<?php if ( $news_query->max_num_pages > 1 ) : ?>
<nav class="pagination">
<?php
echo paginate_links( array(
'total' => $news_query->max_num_pages,
'current' => max( 1, get_query_var( 'paged' ) ),
'format' => '?paged=%#%',
'prev_text' => '« Zurück',
'next_text' => 'Weiter »',
) );
?>
</nav>
<?php endif; ?>
</div>
<?php get_footer(); ?>
Kategorien mit anderen Kriterien kombinieren
Oft müssen Sie die Kategoriefilterung mit anderen Kriterien wie benutzerdefinierten Feldern, Suchbegriffen oder Autorschaft kombinieren. WordPress WP_Query unterstützt all diese Kombinationen durch meta_query und andere Parameter.
<?php
$args = array(
'post_type' => 'event',
'posts_per_page' => 10,
'category__in' => array( get_cat_ID( 'konferenzen' ), get_cat_ID( 'workshops' ) ),
'meta_query' => array(
'relation' => 'AND',
array(
'key' => 'event_datum',
'value' => date( 'Y-m-d' ),
'compare' => '>=',
'type' => 'DATE',
),
array(
'key' => 'event_ort',
'value' => 'Berlin',
'compare' => '=',
),
),
'orderby' => 'meta_value',
'meta_key' => 'event_datum',
'order' => 'ASC',
);
$events = new WP_Query( $args );
if ( $events->have_posts() ) {
while ( $events->have_posts() ) {
$events->the_post();
// Event anzeigen
}
wp_reset_postdata();
}
?>
Zusammenfassung und Empfehlungen
Das Abrufen und Anzeigen von Beiträgen aus Kategorien in WordPress ist eine grundlegende Fähigkeit, die alle Entwickler beherrschen sollten. Die wichtigsten Punkte zu beachten sind:
Für einfache Listen ohne Paginierungsbedarf ist get_posts() die beste Wahl aufgrund der Einfachheit und weil es die Hauptschleife nicht beeinflusst. Für komplexe Ansichten mit Paginierung und erweiterten Filtern ist WP_Query das bevorzugte Werkzeug. Vermeiden Sie query_posts(), es sei denn, Sie müssen explizit die Hauptschleife modifizieren.
Optimierung ist entscheidend für große Websites. Verwenden Sie den fields-Parameter, um zu begrenzen, welche Daten abgerufen werden, no_found_rows, wenn Sie die Gesamtzahl der Ergebnisse nicht benötigen, und die Transient API zum Zwischenspeichern der Ergebnisse. Für dynamische Websites sollten Sie AJAX-Laden für eine bessere Benutzererfahrung in Betracht ziehen.
Denken Sie immer daran, die Beitragdaten mit wp_reset_postdata() zurückzusetzen, nachdem Sie WP_Query oder get_posts() verwendet haben, und validieren und bereinigen Sie alle Benutzereingaben, um Sicherheitsprobleme zu vermeiden.
Häufige Fragen
Wie rufe ich Beiträge aus mehreren Kategorien gleichzeitig ab?
Sie können den category__in-Parameter mit einem Array von Kategorie-IDs verwenden. Zum Beispiel: 'category__in' => array( 12, 15, 18 ). Dies zeigt Beiträge an, die mindestens einer der aufgeführten Kategorien angehören. Wenn Sie Beiträge möchten, die ALLEN Kategorien angehören, verwenden Sie stattdessen category__and.
Wie beziehe ich Unterkategorien in die Abfrage ein?
WordPress bezieht Unterkategorien nicht automatisch ein. Sie müssen entweder alle relevanten Kategorie-IDs manuell auflisten oder eine tax_query mit include_children auf true verwenden. Die einfachste Methode ist, die Funktion get_category_children() oder ähnliches zu verwenden, um alle Unterkategorien zuerst abzurufen.
Wie paginiere ich die Ergebnisse einer benutzerdefinierten Abfrage?
Verwenden Sie WP_Query mit dem paged-Parameter, der auf get_query_var( 'paged' ) gesetzt ist. Verwenden Sie dann die Funktion paginate_links() mit max_num_pages aus der Abfrage. Beachten Sie, dass die Paginierung von WP_Query unabhängig von der Hauptschleife ist.
Wie cache ich Kategorieabfragen für bessere Leistung?
Verwenden Sie die WordPress Transient API. Speichern Sie die Abfrageergebnisse mit set_transient() und rufen Sie sie mit get_transient() ab. Setzen Sie eine passende Ablaufzeit basierend darauf, wie oft der Inhalt aktualisiert wird. Denken Sie daran, den Cache zu invalidieren, wenn neue Beiträge veröffentlicht werden.
Wie schließe ich bestimmte Beiträge von der Kategorieansicht aus?
Verwenden Sie den post__not_in-Parameter mit einem Array von Beitrag-IDs, die Sie ausschließen möchten. Sie können auch category__not_in verwenden, um ganze Kategorien von der Abfrage auszuschließen.



