Hente innlegg fra en kategori i WordPress
Lær mer om profesjonell WordPress-utvikling hos WPPoland.
En av de vanligste oppgavene i WordPress-utvikling er å hente innlegg fra bestemte kategorier. Enten du bygger en tilpasset forsidelayout, oppretter en kategoriarkivmal eller viser relatert innhold, er forståelse av hvordan du effektivt spør etter innlegg per kategori essensiell for enhver WordPress-utvikler.
Denne guiden dekker praktiske tilnærminger til å hente innleggslister fra kategorier, fra enkle implementeringer til avanserte optimaliseringsteknikker.
Slik lagrer WordPress kategorier
Før vi dykker inn i koden, er det viktig å forstå hvordan WordPress håndterer kategorier:
- Kategorier er en innebygd taksonomi i WordPress
- Hvert innlegg kan tilhøre flere kategorier
- Kategorier kan være hierarkiske (forelder/barn-relasjoner)
- Kategoridata lagres i tabellene
wp_termsogwp_term_taxonomy - Innlegg-kategori-relasjoner lagres i
wp_term_relationships
Finne en kategori-ID fra slug eller navn
De fleste spørringsargumenter godtar enten en slug eller en numerisk ID, men ID-baserte argumenter (cat, category__in) er raskest fordi de hopper over et termoppslag. Når du bare kjenner slug-en, løs den opp én gang og gjenbruk ID-en:
// 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');Cache den oppløste ID-en i en konstant eller et option hvis du hardkoder den i en mal. Å kalle get_cat_ID() ved hver forespørsel legger til en spørring du fint kan unngå.
Hente innlegg etter kategori med WP_Query
WP_Query er WordPress sin primære klasse for å spørre etter innlegg. Den tilbyr maksimal fleksibilitet og er den anbefalte tilnærmingen i de fleste tilfeller.
Spørring etter kategori-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();
?>
<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();
}Sporring etter kategori-ID
$args = array(
'cat' => 5,
'posts_per_page' => 5
);
$query = new WP_Query($args);Hente innlegg fra flere kategorier
// Innlegg i NOEN av disse kategoriene (ELLER-relasjon)
$args = array(
'category__in' => array(5, 10, 15),
'posts_per_page' => 10
);
// Innlegg i ALLE disse kategoriene (OG-relasjon)
$args = array(
'category__and' => array(5, 10),
'posts_per_page' => 10
);
// Ekskluder bestemte kategorier
$args = array(
'category__not_in' => array(3, 7),
'posts_per_page' => 10
);Paginere en kategorispørring på en statisk forside
En egen løkke paginerer med paged, som du leser med get_query_var( 'paged' ). Unntaket er en sidemal som er satt som statisk forside: Der lagrer WordPress sidetallet i variabelen page, og derfor sier WP_Query-referansen at du skal lese get_query_var( 'page' ). Med feil variabel viser hvert klikk på “neste” side én igjen.
$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' => 'nyheter',
'posts_per_page' => 10,
'paged' => $paged,
) );Hvilke kategoriparametere tar med underkategorier
Samme kategori-ID gir ulike innleggslister avhengig av hvilket grensesnitt du spør gjennom. Denne detaljen ligger bak de fleste meldinger om at “listen mangler innlegg”, og reglene står i kjernekoden, ikke i innstillinger:
| Grensesnitt | Argument | Innlegg fra underkategorier |
|---|---|---|
| WP_Query | cat | tatt med |
| WP_Query | category_name | tatt med |
| WP_Query | category__in, category__and, category__not_in | ikke tatt med |
| WP_Query | tax_query | tatt med, med mindre include_children er false |
| get_posts() | category | tatt med (alias for cat) |
| REST API | categories=5 | ikke tatt med |
| REST API | categories[terms]=5&categories[include_children]=true | tatt med |
| Query Loop-blokken | kategorifilter | ikke tatt med |
| WP-CLI | --cat, --category_name | tatt med (sendes rett til WP_Query) |
WP_Query-radene kommer fra WP_Query::parse_tax_query(): cat blir en tax query med include_children satt til true, mens category__in, category__and og category__not_in blir tax queries med include_children satt til false. WP_Query-referansen sier det samme i eksemplene sine: category__in viser ikke innlegg fra underkategorier. Raden for get_posts() følger av funksjonsreferansen, som beskriver category som et alias for cat. REST-radene kommer fra posts-kontrolleren, der include_children er false som standard og bare tilbys for hierarkiske taksonomier. Query Loop-raden kommer fra build_query_vars_from_query_block() i kjernens blocks.php, som setter include_children => false fast for hvert taksonomifilter.
Den praktiske følgen: En PHP-mal med cat => 5 og et headless-frontend som kaller /wp/v2/posts?categories=5 kan vise ulike innlegg for samme overordnede kategori. Bestem hvilken oppførsel du trenger, og velg argumentet som gir den, i stedet for å anta at de to stemmer overens.
get_posts() med kategori i WordPress
For enklere bruksområder gir get_posts() et mer direkte API. Den passer godt når du bare trenger en flat liste uten å forholde deg til hovedsløyfen.
$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();Hva get_posts endrer sammenlignet med WP_Query
get_posts() er et tynt lag som bygger en WP_Query med egne standardverdier. Kildekoden til funksjonen viser fire forskjeller som betyr noe for kategorilister:
numberpostser 5 som standard, så et kall uten grense returnerer stille fem innlegg.post_statuserpublishogsuppress_filtersertrue, såposts_whereog lignende SQL-filtre fra utvidelser kjøres ikke. Handlingenpre_get_postskjøres likevel.ignore_sticky_postsogno_found_rowstvinges alltid tiltrue. Du kan ikke bygge nummerert paginering påget_posts(), fordi totalt antall aldri beregnes.includesetterposts_per_pagetil antallet ID-er du sender inn, og overstyrer din egen grense.
En felle til gjelder når du kaller get_posts() inne i en funksjon eller en shortcode-callback. setup_postdata() klargjør mal-taggene, men the_title() og the_permalink() leser fortsatt den globale $post. Deklarer global $post; før løkken foreach ( $posts as $post ), slik eksemplene i funksjonsreferansen gjør, og avslutt med wp_reset_postdata(). Uten den deklarasjonen skriver hvert element i listen ut tittelen på siden shortcoden står på.
Utelate en kategori fra en WordPress-spørring
Utelating fungerer på to måter, og de behandler underkategorier ulikt. En negativ ID i cat utelater kategorien og alle underkategoriene, fordi kjernen bygger en NOT IN-tax query med include_children satt til true. category__not_in utelater bare termene du lister opp, så innlegg i en underkategori vises fortsatt.
// Utelater kategori 12 og alle underkategoriene
$args = array( 'cat' => '-12' );
// Utelater bare innlegg som ligger direkte i 12 eller 34
$args = array( 'category__not_in' => array( 12, 34 ) );For å holde en kategori borte fra bloggforsiden endrer du hovedspørringen i stedet for å kjøre en ekstra løkke. Referansen for pre_get_posts anbefaler nettopp disse betingelsene:
add_action( 'pre_get_posts', function ( $query ) {
if ( ! is_admin() && $query->is_main_query() && $query->is_home() ) {
$query->set( 'cat', '-12' );
}
} );Shortcode som viser innlegg fra en kategori
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>';
}
wp_reset_postdata();
return ob_get_clean();
}
add_shortcode('category_posts', 'category_posts_shortcode');Bruk: [category_posts category="news" posts="5"]
Endre kategoriarkivet med pre_get_posts
function modify_category_queries($query) {
if ($query->is_category() && $query->is_main_query() && !is_admin()) {
$query->set('posts_per_page', 20);
}
}
add_action('pre_get_posts', 'modify_category_queries');Bruk metodeversjonene av betingelsestaggene i callbacken ($query->is_category(), $query->is_main_query()). De frittstående funksjonene tester den globale $wp_query og ikke spørringsobjektet kroken får, noe krokreferansen advarer eksplisitt om.
Hvorfor query_posts er feil verktøy for å filtrere på kategori
Eldre veiledninger setter query_posts( 'cat=5' ) øverst i en mal. Docblocken til query_posts() i kjernen sier at funksjonen overstyrer hovedspørringen fullstendig, ikke er ment for utvidelser eller temaer, og i de fleste tilfeller bør erstattes av handlingen pre_get_posts. Funksjonskroppen er én linje som tilordner en ny WP_Query til den globale $wp_query. En mal kjører etter hovedspørringen, så kallet gjentar databasearbeidet og bytter ut objektet som paginering og betingelsestagger leser fra. Hver kategorioppgave som brukte query_posts(), løses enten med pre_get_posts (endre arkivet) eller med en egen WP_Query (legge til en ekstra liste).
Kombinere kategorier og stikkord med tax_query
Snarveiene cat og category_name er praktiske, men tax_query er argumentet du griper til når kravene blir spesifikke: å kombinere kategorier med etiketter, ekskludere underkategorier eller spørre mot en egendefinert taksonomi. Den uttrykker også AND/OR-logikk eksplisitt, noe snarveisargumentene ikke klarer.
$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);Nøkkelen include_children er detaljen de fleste overser. Som standard trekker en category-tax_query inn alle etterkommertermer, noe et arkiv vanligvis vil ha, men sjelden det en kuratert forsideblokk vil ha:
'tax_query' => array(
array(
'taxonomy' => 'category',
'field' => 'term_id',
'terms' => array(5),
'include_children' => false, // only posts filed directly under term 5
),
),Fordi tax_query fungerer mot enhver taksonomi, henter det samme mønsteret innlegg fra en egendefinert product_cat, portfolio_type eller hvilken som helst taksonomi temaet ditt registrerer, uten en egen funksjon per taksonomi.
Kategorifiltre kan også kombineres med egendefinerte felt. En arrangementsliste som bare viser kommende datoer fra to kategorier, kobler category__in med en meta_query og sorterer på datofeltet:
$args = array(
'posts_per_page' => 10,
'category__in' => array( get_cat_ID( 'Konferanser' ), get_cat_ID( 'Kurs' ) ),
'meta_key' => 'arrangement_dato',
'orderby' => 'meta_value',
'order' => 'ASC',
'meta_query' => array(
array(
'key' => 'arrangement_dato',
'value' => current_time( 'Y-m-d' ),
'compare' => '>=',
'type' => 'DATE',
),
),
);get_cat_ID() tar kategoriens navn, ikke slug, og returnerer 0 når ingenting passer. En 0 i category__in treffer ingen innlegg, så sjekk ID-ene før spørringen kjører på en produksjonsside.
Raskere kategorispørringer med caching
1. Bruk transients for kostbare spørringer
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;
set_transient($cache_key, $posts, HOUR_IN_SECONDS);
}
return $posts;
}2. Begrense hva spørringen henter
Argumentet fields godtar nøyaktig tre verdier, ifølge WP_Query-referansen: all (standard), ids og id=>parent. Alle andre verdier, også en matrise med kolonnenavn, returnerer stille fullstendige innleggsobjekter. To brytere til sparer arbeid for lister som bare skriver ut tittel og lenke:
$args = array(
'category_name' => 'nyheter',
'posts_per_page' => 5,
'no_found_rows' => true, // ingen SQL_CALC_FOUND_ROWS, paginering trengs ikke
'update_post_meta_cache' => false, // egendefinerte felt skrives ikke ut
'update_post_term_cache' => false, // termer skrives ikke ut
);no_found_rows hindrer WordPress i å telle totalt antall treff, som bare trengs for paginering. De to cache-flaggene er true som standard i kjernen; referansen sier at du normalt ikke trenger å endre dem, men slått av sparer de de ekstra meta- og termspørringene når listen aldri leser de dataene. La dem stå på når løkken skriver ut kategorier, stikkord eller egendefinerte felt, fordi forhåndslasting i én spørring er billigere enn én spørring per innlegg.
AJAX, Query Loop og REST-API for kategoriinnlegg
AJAX-lasting av kategoriinnlegg
For en bedre brukeropplevelse kan du implementere AJAX-lasting. To detaljer feller folk: ajaxurl er bare definert i wp-admin, så på frontenden må du sende den inn selv, og hver forespørsel trenger en nonce for å overleve en sikkerhetsgjennomgang.
Kø opp skriptet og gi det admin-ajax-URL-en pluss en 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');Frontend-forespørselen leser deretter fra det lokaliserte objektet:
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);
}
});
});
});Til slutt registrerer du handleren for både innloggede og anonyme besøkende (wp_ajax_ og wp_ajax_nopriv_), verifiserer nonce-en og returnerer den ferdige markupen:
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');Vise kategoriinnlegg i et blokktema
På blokktemaer (standard tematype siden Twenty Twenty-Two kom med WordPress 5.9) trenger du ofte ikke PHP i det hele tatt. Query Loop-blokken filtrert på kategori viser den samme listen fra editoren: sett inn en Query Loop, åpne blokkinnstillingene og legg til kategorien du vil ha under Filtre. Lagre den som et synkronisert mønster, så kan redaktørene slippe den kuraterte listen inn på hvilken som helst side uten å røre en mal. Dette er en av grunnene til at mange norske redaksjoner har gått over til blokktemaer.
Blokkens kategorifilter treffer bare termene du velger. Kjernen gjør det om til en tax query med include_children satt til false, så en valgt overordnet kategori tar ikke med innlegg som bare ligger i underkategoriene; legg underkategoriene til i filteret også.
Grip til kodetilnærmingene over når du trenger logikk blokken ikke kan uttrykke: transient-caching, betingede ekskluderinger per arkiv, eller utdata som konsumeres av noe annet enn temaet (et e-postsammendrag, et REST-svar).
Hente kategoriinnlegg via REST-API-et
For hodeløse frontender, en React-øy eller en ekstern integrasjon eksponerer WordPress kategoriinnlegg over REST-API-et uten at det kreves et eget endepunkt:
GET /wp-json/wp/v2/posts?categories=5&per_page=10&_fields=id,title,link,excerptBruk categories_exclude for å filtrere ut en term, _embed for å hente fremhevede bilder og termnavn i én forespørsel, og _fields for å trimme nyttelasten til det klienten faktisk viser. For å løse en slug til ID-en endepunktet forventer, spør /wp-json/wp/v2/categories?slug=news først.
Tre detaljer fra REST-håndboken avgjør om en headless-liste blir komplett:
- Underkategorier krever objektformen.
categories=5treffer bare term 5. For å ta med underkategoriene sender ducategories[terms]=5&categories[include_children]=true. Samme objekt godtarcategories[operator]=ANDnår et innlegg må ha alle termene du lister opp. - En side gir maks 100 elementer. Pagineringsveiledningen begrenser
per_pagetil en verdi mellom 1 og 100. Les svarhodeneX-WP-TotalogX-WP-TotalPagesog hentpage=2,page=3til du har alt. _fieldsstøtter nestede nøkler. Siden WordPress 5.3 godtar parameteren_fieldsstier sommeta.arrangement_dato, så en liste kan be om én registrert metanøkkel uten hele metaobjektet. WordPress hopper da over beregningen av feltene du ikke ba om, noe som også korter ned svartiden.
Feilsøke en kategorispørring som returnerer feil innlegg
Når en spørring returnerer for mange, for få eller uventede innlegg, undersøk SQL-en den faktisk kjørte i stedet for å gjette på argumentene. Installer Query Monitor, så viser den hver spørring på siden, inkludert den sløyfen din genererte, med de trege markert. For en rask sjekk uten plugin, dump den tolkede spørringen:
$query = new WP_Query($args);
// The exact SQL WordPress built from your $args
error_log($query->request);De to synderne bak de fleste overraskelsene er inkludering av underkategorier (se include_children over) og et villfarent pre_get_posts-filter fra en plugin eller temaet som endrer hovedspørringen. Hvis SQL-en ser riktig ut, men resultatet er tomt, bekreft at termen faktisk har publiserte innlegg tildelt i gjeldende språk eller kontekst, for eksempel når et flerspråklig nettsted har tildelt innleggene til kategoriens versjon på et annet språk.
Liste innlegg fra en kategori med WP-CLI
Til revisjoner, migreringer og engangseksporter kjører wp post list den samme WP_Query fra kommandolinjen. Hvert alternativ --<felt>=<verdi> sendes til WP_Query som argument, så kategorireglene fra tabellen over gjelder uendret:
# Term-ID og antall innlegg for hver kategori
wp term list category --fields=term_id,name,slug,count
# Publiserte innlegg i "nyheter" og underkategoriene, som CSV
wp post list --category_name=nyheter --post_status=publish --fields=ID,post_title,post_date --format=csv
# Bare ID-er, innlegg som ligger direkte i kategori 12 (uten underkategorier)
wp post list --category__in=12 --post_status=publish --format=ids
# Hvor mange innlegg en mal viser for kategori 12 med underkategorier
wp post list --cat=12 --post_status=publish --format=countTo standardverdier skiller seg fra en løkke i en mal. Kildekoden til kommandoen setter posts_per_page til -1 og post_status til any, så uten --post_status=publish inneholder utdataene også utkast, ventende og private innlegg. Standardkolonnene er ID, post_title, post_name, post_date og post_status, og --format godtar table, csv, ids, json, count og yaml. Sammenlign --format=count for --cat og --category__in med samme ID, så ser du raskt hvor mange innlegg som bare ligger i underkategorier.
Vanlige feil med WP_Query og kategorier
- Ikke tilbakestille innleggsdata: Kall alltid
wp_reset_postdata()etter tilpassede sløyfer, ellers risikerer du at oppfølgende kall til hovedsløyfen returnerer feil data. - Spørre ved hver sidelasting: Bruk caching (transients eller objektcache) for kostbare spørringer mot kategorier med mye innhold.
- Ikke sjekke om innlegg finnes: Verifiser alltid
have_posts()før du går inn i sløyfen, ellers feiler tema-tag-kallene stille. - Modifisere hovedspørringen feil: Bruk
pre_get_posts-handlingen i stedet for å opprette nye spørringer på toppen av den eksisterende.
Konklusjon
WordPress tilbyr flere måter å hente innlegg fra kategorier på:
- WP_Query: best for komplekse, tilpassede visninger med multipel filtrering
- get_posts(): ideell for enkle innleggslister i widgets eller relaterte-saker-bokser
- Shortcodes: perfekt for fleksibilitet i Gutenberg eller klassisk redaktør
- pre_get_posts: essensiell for å modifisere arkivsider uten å duplisere kode
Husk å alltid vurdere ytelse, spesielt på nettsteder med store mengder innhold. Implementer caching-strategier og test spørringene dine med verktøy som Query Monitor.







