Når du bygger egne WordPress-temaer for norske redaksjoner, trenger du ofte mer enn en flat kategoriliste. Brødsmuler (breadcrumbs) som viser både gjeldende kategori og dens overordnede gir leseren kontekst, og gir søkemotorer en tydelig sti gjennom innholdsklyngen.
På WordCamp Norge og WordUp Oslo er dette et tema som dukker opp hver gang noen bytter fra «standard kategoriwidget» til et skreddersydd arkiv. Spørsmålet er sjelden «finnes det en funksjon?» - det er «hvilken kategori skal styre stien når innlegget ligger i tre grener samtidig, og hvordan får vi Nynorsk-arkivtitler til å matche Bokmål-brødsmuler uten å hardkode strenger?».
WordPress lagrer hierarki i parent-feltet på term_taxonomy, men get_the_category() returnerer en flat tabell. Denne veiledningen går gjennom fellene, de innebygde hjelpefunksjonene, Primary Category fra Yoast og Rank Math, Schema.org BreadcrumbList, egendefinerte taksonomier og caching - med PHP du kan lime inn i et child theme.
Hvordan WordPress lagrer kategorihierarki
Kategorier er den innebygde hierarkiske taksonomien category. I motsetning til stikkord (post_tag) kan hvert term ha en overordnet (parent).
I databasen er dette ikke en kompleks graf. Hver rad i wp_term_taxonomy har et parent-felt med term_id til direkte forelder. Toppnivå (for eksempel «Teknologi») har parent = 0. Barnet «WordPress» peker på Teknologi, og barnebarnet «Gutenberg» peker på WordPress.
Det betyr at WordPress ikke lagrer en ferdig, flat sti i ett felt. Hvert steg oppover treet krever et oppslag i object cache eller database. Når du bygger brødsmuler, er jobben din å gå den stien deterministisk - ikke å håpe at indeks null i get_the_category() er riktig gren.
På norske redaksjonsnettsteder ser vi ofte tre nivåer: fagområde, undertema og format (for eksempel «Offentlig sektor», «Digitalisering» og «Case»). Arkivmalen for /category/digitalisering/ må da vise både overordnet og gjeldende term. Hvis du bare printer $categories[0]->name, mister leseren konteksten som gjorde at de klikket inn fra forsiden eller et WordCamp Norge-sammendrag.
Et praktisk tips fra WordUp Oslo-sesjoner: tegn treet på en whiteboard før du koder. Redaktører tenker i «mapper», utviklere tenker i term_id. Når de to modellene ikke matcher, ender du med brødsmuler som peker til en søstergren fordi noen huket av feil avkrysningsboks i Gutenberg.
Hvorfor get_the_category() feiler for hierarki
Inne i The Loop er det fristende å starte her:
$categories = get_the_category( $post->ID );Du får en tabell med WP_Term-objekter. To problemer dukker opp raskt:
- Ingen hierarkisk sortering. Har innlegget «Teknologi», «Programmering» og «PHP», sorterer WordPress dem etter navn (term-cachen fylles med
orderby => name), ikke etter dybde i treet. - Flere grener samtidig. En redaktør kan huke av både «PHP» og «Bransjenyheter». Hvilken skal styre stien over tittelen?
Naiv bruk av $categories[0] gir brødsmuler som hopper når alfabetet eller term_id endrer rekkefølgen. På flerspråklige norske nettsteder merkes det ekstra: Bokmål-etiketten «Nyheter» og Nynorsk-etiketten «Nyhende» kan bytte plass i sorteringen selv om strukturen er den samme.
// Unngå dette som eneste kilde til "gjeldende" kategori.
$maybe_primary = $categories[0] ?? null;Et annet fall: get_the_category() respekterer ikke orderby du kanskje forventer fra get_terms(). Den er en tynn wrapper rundt get_the_terms( $post_id, 'category' ). Hvis du trenger eksplisitt sortering (for eksempel etter dybde), må du gjøre det selv etter at tabellen er hentet.
Når innlegget ikke har noen kategori, returnerer funksjonen en tom tabell - ikke false. Sjekk alltid empty( $categories ) før du leser indeks. På eldre temaer som antar at «Uncategorized» alltid finnes, krasjer brødsmulen stille når redaksjonen har slettet standardkategorien og glemt å tilordne en ny.
Hvordan bruke get_category_parents() til brødsmuler
WordPress har en hjelpefunksjon laget for akkurat denne jobben: get_category_parents(). Signaturen ser slik ut:
get_category_parents(
int $category_id,
bool $display_link = false,
string $separator = '/',
bool $nice_name = false,
array $deprecated = array()
): string|WP_ErrorEnkel bruk av get_category_parents()
function wppoland_vis_enkel_hierarki( int $post_id ): void {
$categories = get_the_category( $post_id );
if ( empty( $categories ) ) {
return;
}
$current = $categories[0];
$parents = get_category_parents(
$current->term_id,
true,
' <span class="sep">»</span> '
);
if ( is_wp_error( $parents ) ) {
return;
}
echo '<div class="breadcrumbs-simple">';
echo '<a href="' . esc_url( home_url( '/' ) ) . '">' . esc_html__( 'Forside', 'wppoland' ) . '</a>';
echo ' <span class="sep">»</span> ';
echo $parents; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- WP genererer anker.
echo '<span class="current-title">' . esc_html( get_the_title( $post_id ) ) . '</span>';
echo '</div>';
}Bruk esc_html__() (eller tilsvarende) for «Forside» slik at et Nynorsk-tema kan oversette etiketten uten å røre PHP-logikken. På WordUp Oslo-notater ser man ofte at arkivmalen er oversatt, mens brødsmulen fortsatt sier «Home» fordi noen hardkodet engelsk streng i header.php.
Begrensninger i get_category_parents()
get_category_parents() er praktisk, men:
- Den er låst til
category. For custom taxonomies er ekvivalentenget_term_parents_list()(se neste del). - HTML-en er en streng - vanskelig å cache per segment eller legge til
aria-current. - Den løser ikke Primary Category-konflikten. Du må fortsatt velge riktig
$category_idførst. - Med
$nice_name = truefår du slug i stedet for visningsnavn - nyttig for debug, sjelden for brukervendt UI.
Hvis du trenger å hoppe over toppnivået (noen design vil starte på barn, ikke «Forside » Teknologi»), er heller ikke denne funksjonen egnet. Da er get_ancestors() + egen filtrering av første ledd raskere enn å parse HTML-strengen med regex.
Hvordan bruke get_term_parents_list() i stedet for get_category_parents()
Siden WordPress 4.8.0 er get_category_parents() bare en innpakning: den kaller get_term_parents_list() med taksonomien category. Den samme funksjonen virker med alle hierarkiske taksonomier, også product_cat fra WooCommerce. Argumentene er format (name eller slug), separator, link (standard true) og inclusive (standard true, som legger selve termet til sist). Det femte argumentet til get_category_parents(), $deprecated, har ikke vært i bruk siden 4.8.0 og gir et varsel om utfasing hvis du sender noe inn.
$list = get_term_parents_list(
$term_id,
'product_cat',
array(
'inclusive' => false,
'separator' => ' / ',
)
);
if ( $list && ! is_wp_error( $list ) ) {
echo wp_kses_post( rtrim( $list, ' /' ) );
}Kildekoden i category-template.php viser to særtrekk. Navnet havner i lenken uten esc_html(); bare URL-en går gjennom esc_url(). Og skilletegnet legges til etter hvert element, også det siste, derfor rtrim() i eksempelet. Med 'inclusive' => false utelater du gjeldende term, for eksempel når det allerede står som overskrift under. Beskyttelsen mot en ødelagt foreldrekjede (et term som peker tilbake på en av sine egne etterkommere etter en feilet import) kommer fra get_ancestors(), som stopper så snart en foreldre-ID dukker opp for andre gang.
Hvordan bygge kategori-sti med get_ancestors()
get_ancestors() er den mer fleksible veien. Den fungerer for alle hierarkiske taksonomier og returnerer en tabell med forfedre-ID-er (nærmeste forelder først).
function wppoland_bygg_kategori_sti( int $term_id ): array {
$ancestor_ids = get_ancestors( $term_id, 'category' );
$ancestor_ids = array_reverse( $ancestor_ids ); // fra rot til blad
$trail = array();
foreach ( $ancestor_ids as $ancestor_id ) {
$term = get_category( (int) $ancestor_id );
if ( $term && ! is_wp_error( $term ) ) {
$trail[] = $term;
}
}
$current = get_category( $term_id );
if ( $current && ! is_wp_error( $current ) ) {
$trail[] = $current;
}
return $trail;
}Hvordan rendre brødsmulestien med semantisk HTML
function wppoland_render_breadcrumb_html( array $trail, int $post_id ): string {
if ( empty( $trail ) ) {
return '';
}
$html = '<nav class="breadcrumbs" aria-label="' . esc_attr__( 'Brødsmuler', 'wppoland' ) . '">';
$html .= '<ol class="breadcrumbs__list">';
$html .= '<li class="breadcrumbs__item">';
$html .= '<a href="' . esc_url( home_url( '/' ) ) . '">' . esc_html__( 'Forside', 'wppoland' ) . '</a>';
$html .= '</li>';
foreach ( $trail as $term ) {
$html .= '<li class="breadcrumbs__item">';
$html .= '<a href="' . esc_url( get_category_link( $term->term_id ) ) . '">';
$html .= esc_html( $term->name );
$html .= '</a></li>';
}
$html .= '<li class="breadcrumbs__item breadcrumbs__item--current" aria-current="page">';
$html .= esc_html( get_the_title( $post_id ) );
$html .= '</li>';
$html .= '</ol></nav>';
return $html;
}ol + aria-label er mer tilgjengelig enn en flat div med ». Skjermlesere får en liste, og du kan style separatoren med CSS ::before i stedet for hardkodede tegn.
Sett sammen Primary Category-valget og stien i én helper som single-malen kaller:
function wppoland_single_category_breadcrumb( int $post_id ): string {
$primary = wppoland_finn_primaer_kategori( $post_id );
if ( ! $primary ) {
return '';
}
$trail = wppoland_bygg_kategori_sti( (int) $primary->term_id );
$html = wppoland_render_breadcrumb_html( $trail, $post_id );
$html .= wppoland_breadcrumb_json_ld( $trail, $post_id );
return $html;
}Kall den fra single.php (eller via the_content-filter hvis du av en grunn ikke eier malen). Unngå å duplisere JSON-LD i både tema og SEO-plugin.
Hvordan vise gjeldende kategori på kategoriarkivet
På et kategoriarkiv hjelper ikke get_the_category(): hvert innlegg i listen kan ha flere kategorier, og ingen av dem trenger å være arkivet som vises. Arkivets kategori er det spurte objektet. is_category() bekrefter konteksten, get_queried_object() returnerer arkivets WP_Term, og get_queried_object_id() bare ID-en.
if ( is_category() ) {
$term = get_queried_object();
foreach ( array_reverse( get_ancestors( $term->term_id, 'category', 'taxonomy' ) ) as $ancestor_id ) {
$ancestor = get_term( $ancestor_id, 'category' );
if ( $ancestor && ! is_wp_error( $ancestor ) ) {
printf(
'<a href="%s">%s</a> <span aria-hidden="true">/</span> ',
esc_url( get_term_link( $ancestor ) ),
esc_html( $ancestor->name )
);
}
}
echo '<h1>' . esc_html( $term->name ) . '</h1>';
}Stien over overskriften bygges her fra arkivets eget term, så et innlegg som ligger i tre grener kan ikke flytte den. For selve overskriften holder også single_cat_title(), som skriver ut navnet på gjeldende kategoriarkiv.
Hvordan liste underkategoriene til gjeldende kategori
Motsatt retning av forelderen er listen over barn. wp_list_categories() tar child_of (alle etterkommere av et term) og depth (hvor mange nivåer som skrives ut). En tom title_li fjerner listeelementet med standardoverskriften «Kategorier», slik at du styrer ul selv.
if ( is_category() ) {
echo '<ul class="subcategories">';
wp_list_categories(
array(
'child_of' => get_queried_object_id(),
'depth' => 1,
'title_li' => '',
)
);
echo '</ul>';
}To detaljer fra standardverdiene: hide_empty er 1, så tomme underkategorier mangler til du sender 'hide_empty' => 0. Og child_of uten depth skriver ut hele undertreet, ikke bare nivået rett under. Trenger du data i stedet for HTML, gir get_categories( array( 'parent' => $id ) ) bare de direkte barna, mens get_term_children( $id, 'category' ) gir ID-ene til alle etterkommere på alle nivåer.
Hvordan sjekke om et innlegg ligger i en underkategori
in_category() går via has_category() til is_object_in_term(), og den funksjonen sammenligner bare termene som er tilordnet innlegget direkte. Et innlegg som bare ligger i «WordPress», gir false for in_category( 'teknologi' ) selv om «WordPress» er barn av «Teknologi». For betingelser som «hvor som helst i denne grenen» må du også sjekke forfedrene:
/**
* True if the post is in $parent_id or in any of its descendants.
*/
function wppoland_in_category_branch( $parent_id, $post_id = false ) {
$parent_id = (int) $parent_id;
foreach ( get_the_category( $post_id ) as $term ) {
if ( $term->term_id === $parent_id || cat_is_ancestor_of( $parent_id, $term ) ) {
return true;
}
}
return false;
}cat_is_ancestor_of() kaller term_is_ancestor_of() med taksonomien category og klatrer rekursivt opp gjennom foreldrene. For custom taxonomies kaller du term_is_ancestor_of( $forelder, $barn, $taksonomi ) direkte. Samme sjekk hindrer at et foreldrepunkt i sidemenyen mister aktiv tilstand når leseren står på arkivet til et barnebarn.
Hvordan håndtere Primary Category i Yoast og Rank Math
Når innlegget har flere kategorier, må du velge én gren. SEO-plugins lagrer dette som post meta:
- Yoast SEO:
_yoast_wpseo_primary_category - Rank Math:
rank_math_primary_category
function wppoland_finn_primaer_kategori( int $post_id ): ?WP_Term {
$primary_id = (int) get_post_meta( $post_id, '_yoast_wpseo_primary_category', true );
if ( ! $primary_id ) {
$primary_id = (int) get_post_meta( $post_id, 'rank_math_primary_category', true );
}
if ( $primary_id ) {
$term = get_category( $primary_id );
if ( $term && ! is_wp_error( $term ) ) {
return $term;
}
}
// Fallback: dypeste node i treet.
$categories = get_the_category( $post_id );
if ( empty( $categories ) ) {
return null;
}
$deepest = null;
$max_depth = -1;
foreach ( $categories as $cat ) {
$depth = count( get_ancestors( $cat->term_id, 'category' ) );
if ( $depth > $max_depth ) {
$max_depth = $depth;
$deepest = $cat;
}
}
return $deepest;
}Dypeste node er et fornuftig fallback når Primary Category mangler: den speiler vanligvis den mest spesifikke redaksjonelle plasseringen. Hvis to kategorier har samme dybde, vinner den som kommer sist i løkken - dokumenter det for redaksjonen, eller sorter eksplisitt på term_id for stabilitet.
Yoast og Rank Math kan begge være aktive i migreringsperioder. Les Yoast først bare hvis det er prosjektets sannhetskilde; ellers bytt rekkefølge. Aldri bland: hvis Yoast har en Primary Category og Rank Math en annen, velg én plugin som eier feltet og deaktiver den andres breadcrumb-modul.
For redaktøropplæring: Primary Category er ikke «viktigste SEO-nøkkelord» i markedsføringsspråk - det er «hvilken gren i treet skal brødsmulen følge». Det skillet sparer timer med «hvorfor peker stien til Nyheter når artikkelen handler om PHP».
Hvordan legge til Schema.org BreadcrumbList i JSON-LD
Synlig HTML er ikke nok hvis du vil at Google skal forstå stien. Schema.org BreadcrumbList i JSON-LD er standardformatet.
HTML5-markup for brødsmuler
<nav class="breadcrumbs" aria-label="Brødsmuler">
<ol>
<li><a href="https://eksempel.no/">Forside</a></li>
<li><a href="https://eksempel.no/kategori/teknologi/">Teknologi</a></li>
<li><a href="https://eksempel.no/kategori/teknologi/wordpress/">WordPress</a></li>
<li aria-current="page">Slik bygger du brødsmuler</li>
</ol>
</nav>PHP-funksjon som lager BreadcrumbList i JSON-LD
function wppoland_breadcrumb_json_ld( array $trail, int $post_id ): string {
$items = array();
$position = 1;
$items[] = array(
'@type' => 'ListItem',
'position' => $position++,
'name' => __( 'Forside', 'wppoland' ),
'item' => home_url( '/' ),
);
foreach ( $trail as $term ) {
$items[] = array(
'@type' => 'ListItem',
'position' => $position++,
'name' => $term->name,
'item' => get_category_link( $term->term_id ),
);
}
$items[] = array(
'@type' => 'ListItem',
'position' => $position,
'name' => get_the_title( $post_id ),
'item' => get_permalink( $post_id ),
);
$graph = array(
'@context' => 'https://schema.org',
'@type' => 'BreadcrumbList',
'itemListElement' => $items,
);
return '<script type="application/ld+json">' .
wp_json_encode( $graph, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE ) .
'</script>';
}Hold HTML og JSON-LD i sync. Hvis den synlige stien hopper over «Forside», skal JSON-LD også gjøre det. Dobbel BreadcrumbList (tema + Yoast) gir konflikt - slå av den ene.
Valider med Googles Rich Results Test etter deploy. Typiske feil: position som starter på 0, manglende absolutt URL i item, eller name som er tom fordi get_the_title() kjørte utenfor loop. Bruk alltid eksplisitt $post_id.
På flerspråklige oppsett (Polylang / WPML): term-lenker må speile aktivt språk. get_category_link() respekterer vanligvis språkpluginens filtre, men hardkodede home_url( '/kategori/...' )-strenger gjør det ikke. Hold deg til API-ene.
Hva Google viser fra BreadcrumbList
Googles dokumentasjon for brødsmuler setter minimum: en BreadcrumbList med minst to ListItem, position som starter på 1, og en URL i item på hvert element. Unntaket er det siste elementet: mangler item der, bruker Google URL-en til selve siden. For et innlegg holder forside pluss én kategori allerede, og innleggstittelen som siste element er tillatt, men ikke påkrevd.
Google tillater flere stier for én side og anbefaler en sti som speiler en typisk brukerreise, ikke en som kopierer URL-strukturen. For kategoribrødsmuler er det et argument for Primary Category: den beskriver veien redaksjonen mente, også når permalenken ikke inneholder noen kategori.
Stien vises nå bare på desktop i Google-søk. Siden 23. januar 2025 viser mobilresultatene bare domenet i URL-linjen, slik Search Central-bloggen kunngjorde. Markeringen støttes fortsatt, og rapporten i Search Console blir værende. De synlige brødsmulene i temaet er uansett først og fremst for leseren.
Hvordan vise hierarki for egendefinerte taksonomier
Mange norske innholdssider bruker register_taxonomy() for «tema», «region» eller «fagområde» i stedet for bare category. Da bytter du:
$ancestors = get_ancestors( $term_id, 'fagomrade' );
$term = get_term( $term_id, 'fagomrade' );
$link = get_term_link( $term );get_category_parents() er låst til category. For custom taxonomies bruker du get_term_parents_list() eller get_ancestors() + get_term() + get_term_link(), og sjekk is_wp_error() på lenken. Hierarkiske custom taxonomies oppfører seg som kategorier i parent-modellen, så Primary Category-mønsteret kan gjenskapes med egen post meta-nøkkel hvis redaksjonen trenger det.
Eksempel på en gjenbrukbar helper:
function wppoland_bygg_taksonomi_sti( int $term_id, string $taxonomy ): array {
if ( ! taxonomy_exists( $taxonomy ) ) {
return array();
}
$ancestor_ids = array_reverse( get_ancestors( $term_id, $taxonomy ) );
$trail = array();
foreach ( $ancestor_ids as $ancestor_id ) {
$term = get_term( (int) $ancestor_id, $taxonomy );
if ( $term && ! is_wp_error( $term ) ) {
$trail[] = $term;
}
}
$current = get_term( $term_id, $taxonomy );
if ( $current && ! is_wp_error( $current ) ) {
$trail[] = $current;
}
return $trail;
}Husk: hierarchical => false i register_taxonomy() betyr at parent alltid er 0. Da gir get_ancestors() en tom tabell, og brødsmulen blir bare ett ledd. Det er korrekt oppførsel - ikke en bug.
Hvordan bruke Brødsmuler-blokken i WordPress 7.0 med Primary Category
Siden WordPress 7.0 har kjernen en egen blokk, core/breadcrumbs, som heter «Brødsmuler» i den norske editoren (gjeldende versjon ifølge versjons-API-et til WordPress.org er 7.1.3). block.json lister attributtene separator (standard /), showHomeItem, showCurrentItem, showOnHomePage og prefersTaxonomy. På et innlegg uten foreldreinnlegg bygger blokken stien fra taksonomitermer: den tar den første taksonomien registrert for innleggstypen som har termer, og fra den det første termet get_the_terms() returnerer, via reset( $terms ). Det er samme felle som $categories[0]: uten inngrep vinner det alfabetisk første navnet.
Kildekoden til blokken har filteret block_core_breadcrumbs_post_type_settings til dette. Det forventer en tabell med taxonomy og term, og term er en slug, ikke en ID. Slik sender du Primary Category fra Yoast SEO eller Rank Math til blokken:
add_filter(
'block_core_breadcrumbs_post_type_settings',
static function ( $settings, $post_type, $post_id ) {
if ( 'post' !== $post_type ) {
return $settings;
}
$primary = (int) get_post_meta( $post_id, '_yoast_wpseo_primary_category', true );
if ( ! $primary ) {
$primary = (int) get_post_meta( $post_id, 'rank_math_primary_category', true );
}
$term = $primary ? get_term( $primary, 'category' ) : null;
if ( $term && ! is_wp_error( $term ) ) {
$settings['taxonomy'] = 'category';
$settings['term'] = $term->slug;
}
return $settings;
},
10,
3
);Et annet filter, block_core_breadcrumbs_items, lar deg endre den ferdige listen med label og url før rendering. Markeringen fra blokken dekker det grunnleggende for tilgjengelighet: nav med aria-label, en ol, og siste element som span med aria-current="page". Blokken skriver ikke ut JSON-LD. BreadcrumbList kommer fortsatt fra SEO-pluginen eller fra en funksjon som den over, og begge bør bruke samme term som du gir blokken via filteret.
Hvordan cache kategori-brødsmuler uten ytelsestap
På arkivsidene med mange innlegg koster gjentatte get_ancestors()-kall. Object cache (Redis/Memcached via Drop-in) hjelper fordi get_term() allerede er cachet, men du kan fortsatt memo-isere per request:
function wppoland_cached_trail( int $term_id ): array {
static $cache = array();
if ( isset( $cache[ $term_id ] ) ) {
return $cache[ $term_id ];
}
$cache[ $term_id ] = wppoland_bygg_kategori_sti( $term_id );
return $cache[ $term_id ];
}For fragment-cache (for eksempel i en full page cache foran PHP): cache nøkkelen bør inkludere post_id, Primary Category-ID og språk/locale. Et Bokmål-innlegg og et Nynorsk-arkiv som deler samme term_id men ulike etiketter via språkplugin, må ikke dele samme HTML-fragment.
Transient-cache av hele brødsmulestrengen er sjelden verdt det på enkeltinnlegg. Transient-er betaler seg når du bygger dyre, flernivå-menyer for hele treet - ikke for én sti på single.php.
Invalidér når term endres. Hvis du likevel cacher HTML, heng deg på edited_term og set_object_terms:
add_action( 'edited_category', 'wppoland_flush_breadcrumb_cache' );
add_action( 'set_object_terms', 'wppoland_flush_breadcrumb_cache' );
function wppoland_flush_breadcrumb_cache(): void {
// Slett gruppe-nøkler eller bump en cache-versjon i et options-felt.
delete_option( 'wppoland_breadcrumb_cache_ver' );
add_option( 'wppoland_breadcrumb_cache_ver', (string) time(), '', false );
}En versjonsbump i cache-nøkkelen er enklere enn å spore hver post_id som bruker et gitt term.
Hente kategoriene til et innlegg utenfor The Loop med post-ID
Hjelperne over forutsetter at du har en post-ID, enten fra det globale innlegget inne i The Loop eller etter setup_postdata. I widgeter, REST-callbacks og CLI-skript sender du ID-en eksplisitt:
function wppoland_kategori_sti_for_innlegg( int $post_id ): array {
$categories = get_the_category( $post_id );
if ( empty( $categories ) ) {
return array();
}
$primary = wppoland_finn_primaer_kategori( $post_id ) ?? $categories[0];
return wppoland_bygg_kategori_sti( $primary->term_id );
}Dette betyr mest på arkivkort der du går gjennom mange innlegg: kall aldri get_the_category() uten ID-en til det aktuelle kortet etter at The Loop har gått videre.
Tilgjengelig markup for kategori-brødsmuler
Bruk en <nav> med et tilgjengelig navn (aria-label="Kategori" eller en oversatt streng). Hold den synlige separatoren (» eller /) utenfor lenketeksten, slik at skjermlesere ikke leser “Teknologi høyre dobbel vinkelanførselstegn WordPress” som én sammenhengende frase. Separatorer mellom lenkene, som i ol-versjonen over, er tydeligere.
Ikke la farge alene vise hvilket ledd som er det gjeldende. Det siste leddet kan være ren tekst uten lenke når du allerede står på det arkivet. På enkeltinnlegg forventer redaktører som regel at bladkategorien lenker til arkivet sitt.
Grensetilfeller å teste for kategori-brødsmuler
- Innlegg uten kategorier: returner tidlig, ikke skriv ut en tom nav.
- Foreldreløs parent-ID (slettet forelder):
get_category()kan returnere en feil, så sjekkis_wp_error(). - Multisite og språkplugins: arkivlenkene må følge gjeldende nettsteds URL (
get_category_link()gjør det allerede). - Blokktemaer: bruk en kortkode eller en liten blokk som kaller disse hjelperne, i stedet for å bare redigere
single.php. - Slettet primærterm-ID liggende igjen i Yoast- eller Rank Math-meta: fall tilbake til
get_the_category(). - Kategorinavn med anførselstegn eller og-tegn: alltid
esc_html(). - Import fra CSV eller et gammelt CMS: parent-ID-er kan peke på slettede termer, så stopp stien i stedet for å logge notices.
- Hierarkiet flyttet etter publisering: tøm cachet sti for både den gamle og den nye banen.
Skriv dette som PHPUnit- eller integrasjonstester hvis temaet har CI. Test minst én gang for hånd: et innlegg med to kategorier, en satt primærkategori, en forelder tre nivåer opp og tom object cache.
Kategori-brødsmuler med Polylang og WPML
På flerspråklige nettsteder returnerer get_category_link() URL-en til termen på gjeldende språk når oversettelsespluginen er riktig satt opp. Kontroller likevel at primærkategori-metaen fra Yoast/Rank Math er per språk (eller duplisert) etter en oversettelsesflyt. En polsk primærterm-ID på et engelsk innlegg er en vanlig migreringsfeil.
Hvordan unngå doble brødsmuler og dobbel BreadcrumbList-markup
Hvis informasjonsarkitekturen styres av egendefinerte taksonomier, landingssider eller en manuell brødsmuleplugin, skal du ikke i tillegg skrive ut en ekstra kategoristi. Doble BreadcrumbList JSON-LD og motstridende synlige brødsmuler forvirrer både brukere og validatorer for rike resultater. Velg én kilde per mal.
Oppsummering
- Ikke bruk
$categories[0]som eneste sannhet. - Foretrekk
get_ancestors()når du trenger kontroll; brukget_category_parents()for raske prototyper. - Les Primary Category-meta fra Yoast eller Rank Math, med dybde-fallback.
- Emitter
nav/olog matchende BreadcrumbList JSON-LD. - For custom taxonomies: samme mønster med
get_term/get_term_link.
Flernivå kategorihierarkier er der arkivmaler og brødsmuler sprekker først. Trenger du hjelp til å få hierarkiet riktig på tvers av tema og SEO-plugins, ta kontakt via WordPress-utvikling for arkiver og maler.







