Jak wyświetlić posty z kategorii w WordPress
Dowiedz się więcej o profesjonalnym tworzeniu stron WordPress w WPPoland. Jednym z najczęstszych zadań w tworzeniu WordPress jest pobieranie postów z konkretnych kategorii. Niezależnie od tego, czy budujesz niestandardowy układ strony głównej, tworzysz szablon archiwum kategorii, czy wyświetlasz powiązane treści, zrozumienie jak sprawnie odpytywać posty według kategorii jest niezbędne dla każdego dewelopera WordPress.
Ten przewodnik omawia praktyczne podejścia do pobierania list postów z kategorii, od prostych implementacji po zaawansowane techniki optymalizacji. Po jego lekturze będziesz dysponować kompletnym zestawem narzędzi do obsługi zapytań opartych na kategoriach w każdym projekcie WordPress.
Jak WordPress przechowuje kategorie
Zanim przejdziemy do kodu, warto zrozumieć, jak WordPress obsługuje kategorie:
- Kategorie to wbudowana taksonomia w WordPress
- Każdy post może należeć do wielu kategorii
- Kategorie mogą być hierarchiczne (relacje rodzic-dziecko)
- Dane kategorii są przechowywane w tabelach
wp_termsiwp_term_taxonomy - Relacje post-kategoria są przechowywane w
wp_term_relationships
Zrozumienie tej struktury pomaga pisać bardziej wydajne zapytania i rozwiązywać problemy, gdy się pojawią.
Ustalanie ID kategorii na podstawie sluga lub nazwy
Większość argumentów zapytania przyjmuje slug albo numeryczne ID, ale argumenty oparte na ID (cat, category__in) są najszybsze, bo pomijają wyszukiwanie termu. Gdy znasz tylko slug, rozwiąż go raz i używaj gotowego ID:
// Ze sluga
$term = get_category_by_slug('news');
$news_id = $term ? $term->term_id : 0;
// Z nazwy wyświetlanej
$news_id = get_cat_ID('News'); // zwraca 0, gdy nie znaleziono
// Z dowolnej taksonomii (w tym kategorii)
$term = get_term_by('slug', 'news', 'category');W polskich instalacjach slug często ma lokalną formę (aktualnosci, poradniki), więc nie zakładaj z góry, że odpowiada nazwie wyświetlanej. Jeśli ID wpisujesz w szablonie na sztywno, zapisz je w stałej lub opcji, bo wywoływanie get_cat_ID() przy każdym żądaniu dokłada zbędne zapytanie do bazy.
Posty z kategorii przez WP_Query
WP_Query to podstawowa klasa WordPress do odpytywania postów. Oferuje maksymalną elastyczność i jest zalecanym podejściem w większości przypadków.
Zapytanie według sluga kategorii
$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();
// Wyświetl treść posta
?>
<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();
}Zapytanie według ID kategorii
$args = array(
'cat' => 5, // ID kategorii
'posts_per_page' => 5
);
$query = new WP_Query($args);Jak pobrać posty z wielu kategorii
// Posty w KTÓREJKOLWIEK z tych kategorii (relacja LUB)
$args = array(
'category__in' => array(5, 10, 15),
'posts_per_page' => 10
);
// Posty we WSZYSTKICH tych kategoriach (relacja I)
$args = array(
'category__and' => array(5, 10),
'posts_per_page' => 10
);
// Wykluczenie konkretnych kategorii
$args = array(
'category__not_in' => array(3, 7),
'posts_per_page' => 10
);Kategorie podrzędne w WP_Query
// Pobierz posty z kategorii i wszystkich jej dzieci
$parent_category_id = 5;
$args = array(
'cat' => $parent_category_id,
'posts_per_page' => 20
);
// WP_Query automatycznie uwzględnia kategorie podrzędne przy użyciu 'cat'Paginacja zapytania o kategorię na statycznej stronie głównej
Własna pętla paginuje przez paged, które odczytujesz funkcją get_query_var( 'paged' ). Wyjątkiem jest szablon strony ustawiony jako statyczna strona główna: tam WordPress zapisuje numer strony w zmiennej page, dlatego dokumentacja WP_Query każe czytać get_query_var( 'page' ). Przy złej zmiennej każde kliknięcie “dalej” pokazuje znowu pierwszą stronę.
$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' => 'aktualnosci',
'posts_per_page' => 10,
'paged' => $paged,
) );Które parametry kategorii uwzględniają kategorie podrzędne
To samo ID kategorii zwraca różne listy postów w zależności od interfejsu, przez który je odpytujesz. Ten szczegół stoi za większością zgłoszeń typu “na liście brakuje postów”, a reguły są zapisane w kodzie rdzenia, nie w ustawieniach:
| Interfejs | Argument | Posty z kategorii podrzędnych |
|---|---|---|
| WP_Query | cat | uwzględnione |
| WP_Query | category_name | uwzględnione |
| WP_Query | category__in, category__and, category__not_in | pominięte |
| WP_Query | tax_query | uwzględnione, chyba że include_children ma wartość false |
| get_posts() | category | uwzględnione (to alias cat) |
| REST API | categories=5 | pominięte |
| REST API | categories[terms]=5&categories[include_children]=true | uwzględnione |
| Blok Query Loop | filtr kategorii | pominięte |
| WP-CLI | --cat, --category_name | uwzględnione (trafiają prosto do WP_Query) |
Wiersze WP_Query wynikają z metody WP_Query::parse_tax_query(): cat zamienia się w tax query z include_children ustawionym na true, a category__in, category__and i category__not_in w tax query z include_children ustawionym na false. Dokumentacja WP_Query mówi to samo w przykładach: category__in nie pokazuje postów z kategorii podrzędnych. Wiersz get_posts() wynika z jej dokumentacji, która opisuje category jako alias cat. Wiersze REST API pochodzą z kontrolera postów, gdzie include_children ma domyślnie wartość false i jest dostępne tylko dla taksonomii hierarchicznych. Wiersz Query Loop pochodzi z funkcji build_query_vars_from_query_block() w pliku blocks.php rdzenia, która dla każdego filtra taksonomii wpisuje na sztywno include_children => false.
Skutek praktyczny: szablon PHP z cat => 5 i frontend headless wywołujący /wp/v2/posts?categories=5 mogą pokazać różne posty dla tej samej kategorii nadrzędnej. Zdecyduj, jakiego zachowania potrzebujesz, i wybierz argument, który je daje, zamiast zakładać, że oba się zgadzają.
get_posts z kategorii w WordPress
W prostszych przypadkach get_posts() oferuje bardziej przejrzyste API.
get_posts z ID kategorii
$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 z nazwą kategorii
$posts = get_posts(array(
'category_name' => 'technology',
'numberposts' => 5
));Czym get_posts różni się od WP_Query
get_posts() to cienka nakładka, która buduje WP_Query z własnymi wartościami domyślnymi. Kod funkcji pokazuje cztery różnice istotne przy listach z kategorii:
numberpostsma domyślnie wartość 5, więc wywołanie bez limitu bez ostrzeżenia zwraca pięć postów.post_statusma domyślnie wartośćpublish, asuppress_filterswartośćtrue, więcposts_wherei podobne filtry SQL z wtyczek się nie wykonują. Akcjapre_get_postsnadal się uruchamia.ignore_sticky_postsino_found_rowssą zawsze wymuszone natrue. Naget_posts()nie zbudujesz numerowanej paginacji, bo łączna liczba wyników nigdy nie jest liczona.includeustawiaposts_per_pagena liczbę przekazanych ID i nadpisuje Twój limit.
Jeszcze jedna pułapka dotyczy wywołania get_posts() wewnątrz funkcji albo callbacku shortcodu. setup_postdata() przygotowuje tagi szablonu, ale the_title() i the_permalink() nadal czytają globalną zmienną $post. Zadeklaruj global $post; przed pętlą foreach ( $posts as $post ), tak jak robią to przykłady w dokumentacji funkcji, i zakończ ją wywołaniem wp_reset_postdata(). Bez tej deklaracji każdy element listy wypisze tytuł strony, na której stoi shortcode.
Jak wykluczyć kategorię z zapytania WordPress
Wykluczanie działa na dwa sposoby, a każdy inaczej traktuje kategorie podrzędne. Ujemne ID w cat wyklucza kategorię razem z jej dziećmi, bo rdzeń buduje tax query NOT IN z include_children ustawionym na true. category__not_in wyklucza tylko wskazane termy, więc posty przypisane do kategorii podrzędnej nadal się pojawiają.
// Wyklucza kategorię 12 i wszystkie jej dzieci
$args = array( 'cat' => '-12' );
// Wyklucza tylko posty przypisane bezpośrednio do 12 lub 34
$args = array( 'category__not_in' => array( 12, 34 ) );Żeby usunąć kategorię ze strony głównej bloga, zmień główne zapytanie zamiast uruchamiać drugą pętlę. Dokumentacja pre_get_posts zaleca dokładnie takie warunki:
add_action( 'pre_get_posts', function ( $query ) {
if ( ! is_admin() && $query->is_main_query() && $query->is_home() ) {
$query->set( 'cat', '-12' );
}
} );Shortcode z listą postów z kategorii
Stworzenie shortcodu pozwala edytorom treści wstawiać listy postów z kategorii w dowolnym miejscu.
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>Nie znaleziono postów w tej kategorii.</p>';
}
wp_reset_postdata();
return ob_get_clean();
}
add_shortcode('category_posts', 'category_posts_shortcode');Użycie: [category_posts category="news" posts="5"]
Zmiana archiwum kategorii przez pre_get_posts
Gdy chcesz zmienić, które posty pojawiają się na stronach archiwum kategorii, użyj akcji pre_get_posts.
function modify_category_queries($query) {
// Modyfikuj tylko archiwa kategorii w głównym zapytaniu
if ($query->is_category() && $query->is_main_query() && !is_admin()) {
// Pokaż 20 postów na stronę zamiast domyślnej wartości
$query->set('posts_per_page', 20);
// Wykluczenie postów z konkretnej kategorii na określonych stronach kategorii
$current_cat = get_queried_object();
if ($current_cat->slug === 'featured') {
$query->set('category__not_in', array(10)); // Wyklucz kategorię o ID 10
}
}
}
add_action('pre_get_posts', 'modify_category_queries');W callbacku używaj metod obiektu zamiast samodzielnych tagów warunkowych ($query->is_category(), $query->is_main_query()). Funkcje bez obiektu sprawdzają globalne $wp_query, a nie zapytanie przekazane do hooka, o czym dokumentacja hooka ostrzega wprost.
Dlaczego query_posts nie nadaje się do filtrowania po kategorii
Starsze poradniki wstawiają query_posts( 'cat=5' ) na początek szablonu. Docblock funkcji query_posts() w rdzeniu mówi, że całkowicie nadpisuje ona główne zapytanie, nie jest przeznaczona dla wtyczek ani motywów i w większości przypadków należy ją zastąpić akcją pre_get_posts. Ciało funkcji to jedna linia, która przypisuje nowy WP_Query do globalnego $wp_query. Szablon wykonuje się po głównym zapytaniu, więc wywołanie powtarza pracę bazy danych i podmienia obiekt, z którego czytają paginacja i tagi warunkowe. Każde zadanie z kategoriami, które używało query_posts(), rozwiązuje albo pre_get_posts (zmiana archiwum), albo osobny WP_Query (druga lista).
Filtrowanie postów po kategorii przez tax_query
Skróty cat i category_name są wygodne, ale gdy wymagania robią się bardziej złożone, sięgasz po tax_query: łączenie kategorii z tagami, wykluczanie termów podrzędnych albo odpytywanie własnej taksonomii. To jedyny argument, który jawnie wyraża logikę AND/OR, czego skróty nie potrafią.
$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);Kluczem, który najczęściej się pomija, jest include_children. Domyślnie tax_query dla category wciąga wszystkie termy potomne, co zwykle pasuje do archiwum, ale rzadko do wyselekcjonowanego bloku na stronie głównej:
'tax_query' => array(
array(
'taxonomy' => 'category',
'field' => 'term_id',
'terms' => array(5),
'include_children' => false, // tylko posty przypisane bezpośrednio do termu 5
),
),Ponieważ tax_query działa na dowolnej taksonomii, ten sam wzorzec pobiera posty z własnej product_cat, portfolio_type czy jakiejkolwiek taksonomii zarejestrowanej przez motyw, bez osobnej funkcji dla każdej z nich. W praktyce w sklepach WooCommerce to właśnie tax_query po product_cat zastępuje próby odpytywania kategorii produktów zwykłym cat.
Filtry kategorii łączą się też z polami własnymi. Lista wydarzeń, która pokazuje tylko nadchodzące terminy z dwóch kategorii, łączy category__in z meta_query i sortuje po polu daty:
$args = array(
'posts_per_page' => 10,
'category__in' => array( get_cat_ID( 'Konferencje' ), get_cat_ID( 'Warsztaty' ) ),
'meta_key' => 'data_wydarzenia',
'orderby' => 'meta_value',
'order' => 'ASC',
'meta_query' => array(
array(
'key' => 'data_wydarzenia',
'value' => current_time( 'Y-m-d' ),
'compare' => '>=',
'type' => 'DATE',
),
),
);get_cat_ID() przyjmuje nazwę kategorii, nie slug, i zwraca 0, gdy nic nie pasuje. Zero w category__in nie pasuje do żadnego posta, więc sprawdź ID przed uruchomieniem zapytania na produkcyjnej stronie.
Szybsze zapytania o kategorie dzięki cache
1. Używaj transients dla kosztownych zapytań
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 na 1 godzinę
set_transient($cache_key, $posts, HOUR_IN_SECONDS);
}
return $posts;
}2. Optymalizacja zapytań do bazy danych
// Pobieraj tylko pola, których potrzebujesz
$args = array(
'category_name' => 'news',
'posts_per_page' => 10,
'fields' => 'ids' // Pobieraj tylko ID postów dla lepszej wydajności
);
$query = new WP_Query($args);Argument fields przyjmuje dokładnie trzy wartości, zgodnie z dokumentacją WP_Query: all (domyślnie), ids oraz id=>parent. Każda inna wartość, także tablica nazw kolumn, bez ostrzeżenia zwraca pełne obiekty postów. Dwa kolejne przełączniki oszczędzają pracę przy listach, które wypisują tylko tytuł i link:
$args = array(
'category_name' => 'aktualnosci',
'posts_per_page' => 5,
'no_found_rows' => true, // bez SQL_CALC_FOUND_ROWS, paginacja niepotrzebna
'update_post_meta_cache' => false, // pola własne nie są wypisywane
'update_post_term_cache' => false, // termy nie są wypisywane
);no_found_rows wyłącza liczenie wszystkich pasujących wierszy, których WordPress potrzebuje tylko do paginacji. Obie flagi cache mają w rdzeniu domyślnie wartość true; dokumentacja mówi, że zwykle nie trzeba ich ruszać, ale ich wyłączenie oszczędza dodatkowe zapytania o meta i termy, gdy lista tych danych nie czyta. Zostaw je włączone, gdy pętla wypisuje kategorie, tagi lub pola własne, bo załadowanie cache jednym zapytaniem jest tańsze niż jedno zapytanie na każdy post.
3. Używaj object caching
Jeśli Twoja strona korzysta z object cache (Redis, Memcached), wyniki WP_Query są automatycznie cachowane, co poprawia wydajność przy powtarzających się zapytaniach.
Szablony kategorii, AJAX, Query Loop i REST API
Niestandardowe szablony dla archiwów kategorii
Utwórz plik szablonu category-news.php dla konkretnego stylowania kategorii:
<?php
/* Szablon archiwum dla sluga "news", wybierany przez hierarchię szablonów */
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>Nie znaleziono postów w tej kategorii.</p>
<?php endif; ?>
</div>
<?php get_footer(); ?>Ładowanie postów kategorii przez AJAX
Dla lepszego doświadczenia użytkownika zaimplementuj ładowanie AJAX. Dwa szczegóły najczęściej sprawiają problemy: ajaxurl jest zdefiniowane tylko w wp-admin, więc na frontendzie musisz przekazać je samodzielnie, a każde żądanie potrzebuje nonce, żeby przejść audyt bezpieczeństwa.
Zarejestruj skrypt i przekaż mu adres admin-ajax oraz 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');Żądanie z frontendu odczytuje wtedy dane z zlokalizowanego obiektu:
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);
}
});
});
});Na koniec zarejestruj handler dla użytkowników zalogowanych i anonimowych (wp_ajax_ oraz wp_ajax_nopriv_), zweryfikuj nonce i zwróć wyrenderowany kod:
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(); // wymagane, aby admin-ajax zakończył się czysto
}
add_action('wp_ajax_load_category_posts', 'load_category_posts_handler');
add_action('wp_ajax_nopriv_load_category_posts', 'load_category_posts_handler');Wyświetlanie postów kategorii w motywie blokowym
W motywach blokowych (domyślny typ motywu od czasu, gdy Twenty Twenty-Two trafił do WordPress 5.9) często w ogóle nie potrzebujesz PHP. Blok pętli zapytań (Query Loop) filtrowany po kategorii renderuje tę samą listę z poziomu edytora: wstaw pętlę zapytań, otwórz ustawienia bloku i w sekcji filtrów dodaj wybraną kategorię. Zapisz to jako wzorzec synchronizowany, a redaktorzy będą mogli wstawiać wyselekcjonowaną listę na dowolnej stronie bez dotykania szablonu.
Filtr kategorii w bloku pasuje tylko do zaznaczonych termów. Rdzeń zamienia go na tax query z include_children ustawionym na false, więc wybór kategorii nadrzędnej nie wciąga postów przypisanych wyłącznie do jej dzieci; dodaj do filtra także kategorie podrzędne.
Po podejścia z kodem powyżej sięgaj wtedy, gdy potrzebujesz logiki, której blok nie wyrazi: cachowania w transientach, warunkowych wykluczeń per archiwum albo danych zużywanych poza motywem (biuletyn e-mail, odpowiedź z REST API).
Pobieranie postów kategorii przez REST API
Dla frontendów headless, wyspy Reacta lub zewnętrznej integracji WordPress udostępnia posty kategorii przez REST API, bez potrzeby tworzenia własnego endpointu:
GET /wp-json/wp/v2/posts?categories=5&per_page=10&_fields=id,title,link,excerptUżyj categories_exclude, aby odfiltrować term, _embed, aby jednym żądaniem pobrać obrazki wyróżniające i nazwy termów, oraz _fields, aby ograniczyć payload do tego, co klient faktycznie renderuje. Aby zamienić slug na ID, którego oczekuje endpoint, najpierw odpytaj /wp-json/wp/v2/categories?slug=news.
O tym, czy lista headless jest kompletna, decydują trzy szczegóły z podręcznika REST API:
- Kategorie podrzędne wymagają formy obiektowej.
categories=5pasuje tylko do termu 5. Żeby uwzględnić jego dzieci, wyślijcategories[terms]=5&categories[include_children]=true. Ten sam obiekt przyjmujecategories[operator]=AND, gdy post musi mieć wszystkie wskazane termy. - Strona ma limit 100 elementów. Przewodnik po paginacji ogranicza
per_pagedo wartości od 1 do 100. Odczytaj nagłówki odpowiedziX-WP-TotaliX-WP-TotalPagesi pobierajpage=2,page=3, aż zbierzesz wszystko. _fieldsobsługuje klucze zagnieżdżone. Od WordPress 5.3 parametr_fieldsprzyjmuje ścieżki takie jakmeta.data_wydarzenia, więc lista może pobrać jeden zarejestrowany klucz meta bez całego obiektu meta. WordPress pomija wtedy wyliczanie pól, o które nie prosisz, co skraca też czas odpowiedzi.
Debugowanie zapytania kategorii zwracającego niewłaściwe posty
Gdy zapytanie zwraca za dużo, za mało albo nieoczekiwane posty, obejrzyj SQL, który faktycznie się wykonał, zamiast zgadywać po argumentach. Zainstaluj Query Monitor, a pokaże każde zapytanie na stronie, w tym to wygenerowane przez Twoją pętlę, z oznaczeniem wolnych. Do szybkiego sprawdzenia bez wtyczki wypisz sparsowane zapytanie:
$query = new WP_Query($args);
// Dokładny SQL, który WordPress zbudował z Twoich $args
error_log($query->request);Za większością niespodzianek stoją dwie przyczyny: uwzględnianie termów podrzędnych (patrz include_children powyżej) oraz zabłąkany filtr pre_get_posts z wtyczki lub motywu zmieniający główne zapytanie. Jeśli SQL wygląda poprawnie, a wynik jest pusty, upewnij się, że do termu naprawdę są przypisane opublikowane posty w bieżącym języku lub kontekście, o czym łatwo zapomnieć przy WPML czy Polylang.
Jak wylistować posty z kategorii przez WP-CLI
Przy audytach, migracjach i jednorazowych eksportach wp post list uruchamia ten sam WP_Query z wiersza poleceń. Każda opcja --<pole>=<wartość> trafia do WP_Query jako argument, więc reguły z tabeli powyżej działają bez zmian:
# ID termu i liczba postów w każdej kategorii
wp term list category --fields=term_id,name,slug,count
# Opublikowane posty z "aktualnosci" i jej kategorii podrzędnych, jako CSV
wp post list --category_name=aktualnosci --post_status=publish --fields=ID,post_title,post_date --format=csv
# Same ID, posty przypisane bezpośrednio do kategorii 12 (bez dzieci)
wp post list --category__in=12 --post_status=publish --format=ids
# Ile postów pokaże szablon dla kategorii 12 i jej dzieci
wp post list --cat=12 --post_status=publish --format=countDwie wartości domyślne różnią się od pętli w szablonie. Kod polecenia ustawia posts_per_page na -1 i post_status na any, więc bez --post_status=publish wynik zawiera szkice, posty oczekujące i prywatne. Domyślne kolumny to ID, post_title, post_name, post_date i post_status, a --format przyjmuje table, csv, ids, json, count i yaml. Porównanie --format=count dla --cat i --category__in przy tym samym ID szybko pokazuje, ile postów siedzi wyłącznie w kategoriach podrzędnych.
Najczęstsze błędy WP_Query przy kategoriach
- Brak resetowania danych posta: zawsze wywołuj
wp_reset_postdata()po niestandardowych pętlach - Odpytywanie przy każdym ładowaniu strony: używaj cachowania dla kosztownych zapytań
- Brak sprawdzenia istnienia postów: zawsze weryfikuj
have_posts()przed pętlą - Nieprawidłowa modyfikacja głównego zapytania: używaj
pre_get_postszamiast tworzenia nowych zapytań na stronach archiwum - Ignorowanie paginacji: pamiętaj o obsłudze paginacji dla dużych archiwów kategorii
Podsumowanie
WordPress oferuje wiele sposobów pobierania postów z kategorii, z których każdy jest odpowiedni w różnych sytuacjach:
- WP_Query: najlepsza do złożonych, niestandardowych wyświetleń
- get_posts(): idealna do prostych list postów
- Shortcody: doskonałe dla elastyczności edytorów treści
- pre_get_posts: niezbędne do modyfikowania stron archiwum
Zrozumienie tych metod i wiedza, kiedy korzystać z każdej z nich, sprawi, że staniesz się bardziej efektywnym deweloperem WordPress. Pamiętaj, aby zawsze brać pod uwagę wydajność, szczególnie na stronach z dużą ilością treści.
W przypadku stron produkcyjnych wdróż strategie cachowania i testuj zapytania narzędziami takimi jak Query Monitor, aby zapewnić optymalną wydajność.







