Jak pobrać nazwę kategorii bez linku w WordPress? (Get_the_category)

Jak pobrać nazwę kategorii bez linku w WordPress? (Get_the_category)

Ostatnio zweryfikowano: 21 września 2026
10 min czytania
Poradnik
500+ projektów WP
Full-stack developer

Standardowa funkcja WordPressa the_category() jest wygodna na liście wpisów w klasycznym motywie, ale ma jedną sztywną cechę: zawsze generuje linki HTML (<a href="...">...</a>) do archiwum kategorii. Gdy budujesz kartę bloga, badge w gridzie portfolio albo meta w hero single, kategoria ma często być samym tekstem albo klasą CSS, a nie klikalnym elementem. W tym artykule pokazujemy, jak wyjść z kotwic i pracować na obiektach terminów.

Rozwiązaniem jest get_the_category(), która zwraca tablicę obiektów (w praktyce WP_Term), a nie gotowy markup. Oficjalna dokumentacja: get_the_category(), the_category() oraz get_the_terms().

#Dlaczego the_category() zawsze wypisuje kotwice

the_category() to tag szablonu w sensie WordPressa: funkcja przeznaczona do wyświetlenia wyniku, nie do zwrócenia danych do dalszej obróbki. Wewnętrznie opiera się na get_the_category_list(), która składa listę linków z separatorem i opcjonalnym rodzicielskim kontekstem. Parametry sterują separatorem, rodzicami i post ID, ale nie trybem „tylko tekst”.

To nie jest bug. Architektura tagów szablonów z lat 2000 zakładała, że motyw wypisuje HTML od razu w pliku PHP. Dziś ten model koliduje z komponentami, block theme’ami i miejscami, gdzie nazwa trafia do atrybutu, JSON-LD albo cache’owanego meta. Gdy potrzebujesz stringa bez markup, nie walcz z the_category() - sięgnij po getter.

Na WordUpach w Trójmieście ten temat wraca regularnie: ktoś pokazuje „dlaczego badge jest niebieski i klikalny”, a odpowiedź jest zawsze ta sama - w szablonie siedzi the_category() zamiast odczytu ->name.

#Kształt obiektu z get_the_category()

<?php
$categories = get_the_category();

if ( ! empty( $categories ) ) {
    echo esc_html( $categories[0]->name );
}
?>

get_the_category( $post_id = false ) bez argumentu bierze bieżący post z globalnego $post (w pętli). Zwracana tablica zawiera obiekty terminów taksonomii category. Pola, z których korzystasz na co dzień:

  • name - wyświetlana nazwa (to, czego zwykle chcesz bez linku)
  • slug - bezpieczny identyfikator pod klasy CSS i ścieżki
  • term_id - ID terminu w tabeli terms
  • term_taxonomy_id - ID w term_taxonomy (rzadziej potrzebne w szablonach)
  • description - opis kategorii z panelu
  • count - liczba obiektów przypisanych do terminu
  • parent - ID rodzica w hierarchii kategorii
  • taxonomy - zwykle string category

Pusta tablica oznacza brak kategorii. Nie zakładaj, że każdy post ma przynajmniej jedną: importy, CPT z wyłączoną taksonomią albo ręczne czyszczenie danych potrafią zostawić pustkę. Zawsze ! empty( $categories ) przed indeksem [0].

Kolejność elementów w tablicy nie jest kontraktem „pierwsza = primary”. To kolejność zwrócona przez warstwę termów i cache obiektów. Jeśli SEO wymaga jednej „głównej” kategorii, czytaj meta wtyczki (sekcja niżej), a nie ślepo [0].

#Escapowanie: esc_html, esc_attr i kontekst wyjścia

Nazwa kategorii pochodzi z bazy i może zawierać cudzysłowy, ampersandy albo znaki, które w HTML łamią atrybuty. Reguła jest prosta:

  • treść między tagami: esc_html( $term->name )
  • wartość atrybutu (class, data-*, aria-label): esc_attr( $term->slug ) lub esc_attr( $term->name ) zależnie od tego, co wstawiasz
  • URL archiwum (gdy jednak potrzebujesz linku): esc_url( get_category_link( $term->term_id ) )
<?php
$cats = get_the_category();
$first = ! empty( $cats ) ? $cats[0] : null;

if ( $first ) : ?>
    <span class="badge badge-<?php echo esc_attr( $first->slug ); ?>">
        <?php echo esc_html( $first->name ); ?>
    </span>
<?php endif; ?>

Nie mieszaj: echo $category->name w motywie produkcyjnym to dług techniczny. Motywy, które piszemy pod klientów (i które omawiamy przy wdrożeniach custom theme), zakładają escapowanie przy każdym wyjściu do HTML.

#Wiele kategorii: foreach i implode

Jeden wpis może mieć kilka kategorii. Lista tekstowa bez linków buduje się z tablicy nazw, nie z gotowego HTML:

<?php
$categories = get_the_category();
$names     = array();

if ( ! empty( $categories ) ) {
    foreach ( $categories as $category ) {
        $names[] = esc_html( $category->name );
    }
    echo implode( ', ', $names );
}
?>

Warianty warte rozważenia:

  • separator lokalny: w PL często , albo ·; unikaj twardego &nbsp; bez powodu
  • limit: jeśli UI pokazuje tylko dwie etykiety, array_slice( $categories, 0, 2 ) przed pętlą
  • unikalność: przy dziwnych danych z migracji array_unique( $names ) chroni przed podwójnym badge

Gdy potrzebujesz jednocześnie nazwy i sluga (np. lista <li> z klasami), trzymaj obiekty dłużej i escapuj przy echo, zamiast wcześniej sklejać HTML w stringu.

#Antywzorzec: strip_tags na liście kategorii

Spotykany skrót wygląda tak:

<?php
// Antywzorzec - nie kopiuj do produkcji
echo strip_tags( get_the_category_list( ', ' ) );
?>

Dlaczego to zły pomysł:

  1. Generujesz pełny HTML z kotwicami, a potem go niszczysz - zbędna praca CPU i cache obiektów i tak już masz przy getterze.
  2. strip_tags nie zastępuje esc_html. Usuwa tagi, ale nie normalizuje encji w kontekście, w którym string potem ląduje.
  3. Zmiana separatora, filtrów the_category / get_the_category_list albo HTML z wtyczek SEO potrafi zostawić śmieci w tekście.
  4. Tracisz dostęp do slug i term_id w tym samym przebiegu - przy badge’ach i schema i tak wrócisz do obiektów.

Ten sam antywzorzec pojawia się przy the_tags() / get_the_tag_list(). Wzorzec naprawczy jest wspólny: get_the_terms() albo dedykowany getter, potem własne składanie stringa.

#Własne taksonomie: get_the_terms()

Kategorie (category) i tagi (post_tag) to tylko dwie wbudowane taksonomie. Produkty WooCommerce, CPT portfolio, lokalizacje czy „branże” klientów siedzą we własnych rejestracjach. Tam get_the_category() milczy - nie dlatego, że „nic nie ma”, tylko dlatego, że patrzysz w złą taksonomię.

<?php
$post_id = get_the_ID();
$terms   = get_the_terms( $post_id, 'branża' );

if ( is_wp_error( $terms ) || empty( $terms ) ) {
    return;
}

$names = array();
foreach ( $terms as $term ) {
    $names[] = esc_html( $term->name );
}
echo implode( ', ', $names );
?>

get_the_terms() zwraca:

  • tablicę WP_Term przy sukcesie
  • false, gdy brak termów
  • WP_Error przy problemie (np. niezarejestrowana taksonomia w danym kontekście)

Zawsze rozróżniaj is_wp_error() od pustki. W logach stagingu Trójmiasta widzieliśmy motywy, które traktowały WP_Error jak pustą tablicę i gubiły sygnał konfiguracyjny (taksonomia niezaładowana na froncie).

Pokrewne funkcje:

  • wp_get_post_terms() - więcej kontroli (pola, orderby), przydatne poza szablonem
  • get_terms() - zapytanie po taksonomii bez konkretnego posta
  • has_term() - warunek w layoutcie bez budowania listy

#Primary category z wtyczek SEO

Yoast SEO, Rank Math i podobne wtyczki pozwalają redaktorowi wskazać „główną” kategorię przy wielu przypisaniach. Indeks [0] z get_the_category() tej decyzji nie zna.

Typowy odczyt (sprawdź aktualny klucz meta w swojej wersji wtyczki - nazwy bywały migracyjne):

<?php
$post_id = get_the_ID();

// Przykład wzorca Yoast - zweryfikuj klucz w swojej instalacji
$primary_id = (int) get_post_meta( $post_id, '_yoast_wpseo_primary_category', true );

if ( $primary_id > 0 ) {
    $term = get_term( $primary_id, 'category' );
    if ( $term && ! is_wp_error( $term ) ) {
        echo esc_html( $term->name );
        return;
    }
}

// Fallback: pierwsza z get_the_category()
$categories = get_the_category( $post_id );
if ( ! empty( $categories ) ) {
    echo esc_html( $categories[0]->name );
}
?>

Rank Math i inne pakiety mają własne meta albo helpery API. W projekcie agencyjnym warto wyciągnąć ten odczyt do jednej funkcji motywu (wppoland_get_primary_category_name( $post_id )), żeby single, karty archiwum i feed RSS nie rozjeżdżały się logiką.

Bez primary meta decyzja biznesowa powinna być świadoma: alfabet, najpłytszy rodzic, albo kategoria z najwyższym count to trzy różne semantyki. Zapisz wybór w kodzie komentarzem, nie zgaduj przy code review.

#Motywy blokowe i FSE: gdzie PHP jeszcze ma sens

W Full Site Editing nazwy kategorii często wychodzą z bloku Post Terms albo wzorców query loop. Blok domyślnie linkuje termy - to ten sam kontrakt UX co the_category(), tylko w HTML-u zapisanym w theme.json / markup bloku.

Gdy potrzebujesz tekstu bez linku w FSE:

  1. Sprawdź ustawienia bloku Post Terms (niektóre wersje pozwalają wyłączyć linki w inspectorze).
  2. Jeśli nie - użyj bloku Shortcode albo własnego bloku dynamicznego, który w render_callback woła get_the_category() / get_the_terms().
  3. Alternatywa: filtruj output bloku przez render_block tylko dla konkretnego blockName i kontekstu szablonu - ostrożnie, bo łatwo zepsuć edytor.

Klasyczny single.php / content-card.php nadal jest najczytelniejszym miejscem na pełną kontrolę nad badge’ami. Hybrydy (FSE + klasyczne części szablonu) są normalne w utrzymywanych witrynach klientów; nie trzeba przepisywać całego motywu, żeby dostać esc_html( $term->name ) w jednym komponencie karty.

W block theme pamiętaj o kontekście zapytania: w niektórych callbackach get_the_ID() bywa puste, jeśli nie przekażesz postId z kontekstu bloku. Wtedy jawne $attributes['postId'] albo get_queried_object_id() ratuje odczyt.

#Cache nazw kategorii pod meta i karty

Na archiwach i homepage’ach z gęstą siatką kart wielokrotne wołanie termów na post to zwykle koszt akceptowalny dzięki object cache WordPressa. Problemy zaczynają się, gdy:

  • składasz własny REST / GraphQL / headless payload i serializujesz nazwy do JSON przy każdym requeście bez cache
  • budujesz meta description albo Open Graph w pętli bez transientu przy ciężkim importcie
  • generujesz programatycznie tysiące stron (np. lokalne landingi) i przy każdym URL powtarzasz te same get_the_terms

Wzorzec, który utrzymujemy w projektach:

<?php
function wppoland_cached_category_names( $post_id ) {
    $post_id = (int) $post_id;
    $key     = 'wpp_cat_names_' . $post_id;
    $cached  = wp_cache_get( $key, 'wppoland' );

    if ( false !== $cached ) {
        return $cached;
    }

    $categories = get_the_category( $post_id );
    $names      = array();

    if ( ! empty( $categories ) ) {
        foreach ( $categories as $category ) {
            $names[] = $category->name; // escapuj przy wyjściu do HTML
        }
    }

    wp_cache_set( $key, $names, 'wppoland', HOUR_IN_SECONDS );
    return $names;
}
?>

Invalidacja: podłącz set_object_terms / edited_term / deleted_term, żeby czyścić klucz przy zmianie przypisań. Trzymanie już zescapowanego HTML w cache utrudnia użycie tej samej listy w JSON-LD (tam zwykle chcesz surowy tekst i inne escapowanie). Cache’uj dane, escapuj przy renderze.

Do meta tagów (np. własny article:section) bierz primary name z poprzedniej sekcji, nie sklejaj pięciu kategorii w jeden string bez limitu długości - crawlerom i podglądom social i tak wystarczy jeden czytelny sygnał.

#Gotowy snippet do single.php i kart

Minimalny wariant pierwszej kategorii:

<?php
$categories = get_the_category();

if ( ! empty( $categories ) ) {
    echo esc_html( $categories[0]->name );
}
?>

Lista po przecinku - jak wyżej w sekcji o implode. Badge ze slugiem - sekcja o escapowaniu. Primary z meta - sekcja SEO. Własna taksonomia - get_the_terms().

Ten sam kontrakt danych (WP_Term + esc_*) obowiązuje w shortcode’ach, widgetach klasycznych i render_callback bloków. Różni się tylko sposób przekazania $post_id.

#Checklist wdrożeniowy

Zanim uznasz zadanie za zamknięte w motywie:

  1. Zero the_category() / get_the_category_list() + strip_tags w miejscach „tylko tekst”.
  2. Każde wyjście nazwy przez esc_html lub esc_attr według kontekstu.
  3. Jawna taksonomia przy CPT (get_the_terms, nie get_the_category).
  4. Primary category zgodna z wtyczką SEO, jeśli redakcja z niej korzysta.
  5. W FSE: decyzja blok vs PHP callback, bez ukrytego linkowania w Post Terms.
  6. Cache nazw tylko jako dane; invalidacja przy zmianie termów.

Jeśli szablon robi się nieutrzymywalny przez narosłe wyjątki kategorii, tagów i CPT, sensowniej jest uporządkować warstwę termów w motywie albo przepisać motyw od podstaw niż dokładać kolejne strip_tags.

#Podsumowanie

the_category() zawsze buduje kotwice, bo tak został zaprojektowany tag szablonu. get_the_category() daje tablicę obiektów z name, slug, term_id i resztą metadanych - z tego składasz czysty tekst, badge albo meta. Własne taksonomie obsługuj przez get_the_terms(), primary category czytaj z meta wtyczki SEO, a strip_tags na listach HTML odłóż do historii. W block theme’ach kontroluj blok Post Terms albo własny render PHP. Nazwy pod meta i karty cache’uj jako dane, escapuj przy wyjściu.

Dokumentacja startowa na developer.wordpress.org: get_the_category, the_category, get_the_terms.

Następny krok

Przekuj artykuł w realne wdrożenie

Pod tym wpisem dokładam linki, które domykają intencję użytkownika i prowadzą dalej w strukturze serwisu.

Chcesz wdrożyć ten temat na swojej stronie?

Jeśli chcesz przełożyć wiedzę z artykułu na działającą stronę, sklep albo przebudowę serwisu, przygotuję konkretny zakres prac.

Powiązany klaster

Sprawdź inne usługi WordPress i bazę wiedzy

Wzmocnij swój biznes dzięki profesjonalnemu wsparciu technicznemu w kluczowych obszarach ekosystemu WordPress.

FAQ do artykułu

Często zadawane pytania

Najważniejsze odpowiedzi, które pomagają wdrożyć temat w praktyce.

SEO-readyGEO-readyAEO-ready4 Q&A
Dlaczego the_category() nie potrafi zwrócić samego tekstu?#
Funkcja jest tagiem szablonu przeznaczonym do wyświetlenia listy kategorii jako linków do archiwów. W rdzeniu buduje znaczniki a href i wypisuje je od razu. Nie ma parametru, który wyłącza kotwice. Do czystej nazwy służy get_the_category() albo get_the_terms().
Czy strip_tags(get_the_category_list()) to dobry skrót?#
Nie. Najpierw generujesz HTML z linkami, a potem go obcinasz. Tracisz kontrolę nad escapowaniem, atrybutami i kolejnością, a przy zmianie separatora w rdzeniu łatwo o niespodzianki. Pobieraj obiekty terminów i buduj string z esc_html().
Jak wziąć nazwę z własnej taksonomii, nie z category?#
Użyj get_the_terms( $post_id, 'twoja_taksonomia' ). Zwraca tablicę obiektów WP_Term albo false lub WP_Error. Obsłuż błąd i pustą tablicę, potem czytaj ->name tak samo jak przy kategoriach.
Co z primary category z Yoast lub Rank Math?#
Te wtyczki zapisują wybrane ID w meta wpisu. Odczytaj meta, pobierz termin przez get_term() i dopiero wtedy wypisz nazwę. Indeks [0] z get_the_category() nie musi być kategorią oznaczoną jako główna.

Potrzebujesz FAQ dopasowanego do branży i rynku? Przygotujemy wersję pod Twoje cele biznesowe.

Porozmawiajmy

Polecane artykuły