A exibição correta da hierarquia de categorias é fundamental para a navegação do utilizador e para SEO. Quando um visitante acessa um post, saber em que categoria e subcategoria ele se encontra ajuda na orientação e melhora a experiência do utilizador. Além disso, URLs de categorias bem estruturadas contribuem para o posicionamento nos motores de busca.
O WordPress utiliza um sistema de taxonomia flexível que permite criar hierarquias de categorias com múltiplos níveis. Contudo, extrair e exibir essas relações hierárquicas requer conhecimento das funções adequadas e da estrutura de dados do WordPress.
Este guia completo ensina todas as técnicas para exibir categorias atuais, pais e hierarquias completas nos seus temas e plugins WordPress.
Fundamentos da Taxonomia WordPress
O que são Categorias?
Categorias são uma das duas taxonomias nativas do WordPress (a outra sendo tags). A principal diferença é que categorias são hierárquicas, o que significa que podem ter categorias “pai” e “filho”, enquanto tags são planas e não hierárquicas.
Características das categorias:
- Podem ser organizadas em múltiplos níveis de profundidade
- Cada post pode pertencer a múltiplas categorias
- Categorias não utilizadas são mantidas no sistema
- A estrutura hierárquica é armazenada no campo
parentda tabelawp_term_taxonomy
Estrutura de Dados
O WordPress armazena informações de categorias em várias tabelas do banco de dados:
Tabela wp_terms
Armazena os termos (categorias, tags, etc.) com os campos principais:
term_id: Identificador úniconame: Nome da categoriaslug: Versão URL-friendly do nometerm_group: Agrupamento de termos sinónimos
Tabela wp_term_taxonomy
Armazena as relações taxonómicas:
term_taxonomy_id: Identificador únicoterm_id: Referência para wp_termstaxonomy: Tipo de taxonomia (category, post_tag, etc.)parent: ID da categoria pai (0 se não houver pai)count: Número de posts nessa categoria
O Objeto de Categoria
Quando você obtém uma categoria no WordPress, recebe um objeto com as seguintes propriedades:
$category = get_category( 5 );
// Propriedades disponíveis:
echo $category->term_id; // ID da categoria
echo $category->name; // Nome (ex: "Tecnologia")
echo $category->slug; // Slug (ex: "tecnologia")
echo $category->parent; // ID do pai (0 se for categoria raiz)
echo $category->count; // Número de posts
echo $category->description; // Descrição da categoria
echo $category->cat_ID; // Mesmo que term_id
echo $category->category_count; // Mesmo que count
echo $category->category_description; // Mesmo que description
echo $category->cat_name; // Mesmo que name
echo $category->category_nicename; // Mesmo que slug
echo $category->category_parent; // Mesmo que parent
Método Básico: get_the_category() com Verificação de Pai
Função Simples para Categoria Pai e Atual
Esta é a solução mais direta para exibir apenas um nível de hierarquia (pai e filho):
/**
* Obtém a hierarquia de categoria (pai e atual) para o post atual
*
* @return string|false HTML da hierarquia ou false se não houver categorias
*/
function wppoland_get_category_hierarchy() {
// Obter todas as categorias do post atual
$categories = get_the_category();
// Se não houver categorias, retornar false
if ( empty( $categories ) ) {
return false;
}
// Usar a primeira categoria como base
$category = $categories[0];
$output = '';
// Se a categoria tem um pai, exibir primeiro
if ( $category->parent ) {
$parent = get_category( $category->parent );
$parent_link = get_category_link( $parent->term_id );
$output .= '<a href="' . esc_url( $parent_link ) . '" class="category-parent">';
$output .= esc_html( $parent->name ) . '</a>';
$output .= '<span class="breadcrumb-separator"> » </span>';
}
// Categoria atual
$current_link = get_category_link( $category->term_id );
$output .= '<a href="' . esc_url( $current_link ) . '" class="category-current">';
$output .= esc_html( $category->name ) . '</a>';
return $output;
}
Uso no Template do Tema
<?php
// No seu template (single.php, archive.php, etc.)
if ( function_exists( 'wppoland_get_category_hierarchy' ) ) {
$hierarchy = wppoland_get_category_hierarchy();
if ( $hierarchy ) {
echo '<nav class="category-breadcrumb" aria-label="Breadcrumb">';
echo $hierarchy;
echo '</nav>';
}
}
?>
CSS para Estilização
.category-breadcrumb {
font-size: 14px;
color: #666;
margin-bottom: 20px;
padding: 10px 15px;
background: #f9f9f9;
border-radius: 4px;
}
.category-breadcrumb a {
color: #0073aa;
text-decoration: none;
transition: color 0.2s ease;
}
.category-breadcrumb a:hover {
color: #00a0d2;
text-decoration: underline;
}
.breadcrumb-separator {
margin: 0 8px;
color: #999;
}
.category-parent {
font-weight: 500;
}
.category-current {
}
Método Avançado: Trilha Breadcrumb Completa
Para exibir toda a hierarquia (múltiplos níveis de ancestrais), precisamos de uma função recursiva:
/**
* Obtém a trilha completa de categorias do post
* Inclui todos os níveis: avô, pai, filho, neto
*
* @param int|null $post_id ID do post (opcional)
* @return string HTML da trilha breadcrumb
*/
function wppoland_get_full_category_trail( $post_id = null ) {
// Se não for especificado, usar o post atual
if ( ! $post_id ) {
$post_id = get_the_ID();
}
// Obter categorias do post
$categories = get_the_category( $post_id );
if ( empty( $categories ) ) {
return '';
}
// Usar a primeira categoria
$category = $categories[0];
// Array para armazenar a trilha
$trail = array();
// Percorrer hierarquia de baixo para cima
while ( $category->parent ) {
$category = get_category( $category->parent );
array_unshift( $trail, $category );
}
// Adicionar a categoria atual ao início
array_unshift( $trail, get_category( $categories[0]->term_id ) );
// Se a trilha só tem um elemento (categoria raiz), retornar apenas ela
if ( count( $trail ) === 1 ) {
$cat = $trail[0];
return '<a href="' . esc_url( get_category_link( $cat->term_id ) ) . '">'
. esc_html( $cat->name ) . '</a>';
}
// Construir HTML da trilha
$output = '<nav class="breadcrumb-trail" aria-label="Breadcrumb">';
$output .= '<ol class="breadcrumb-list">';
foreach ( $trail as $index => $cat ) {
$is_last = ( $index === count( $trail ) - 1 );
$output .= '<li class="breadcrumb-item' . ( $is_last ? ' active' : '' ) . '">';
if ( ! $is_last ) {
$output .= '<a href="' . esc_url( get_category_link( $cat->term_id ) ) . '">';
$output .= esc_html( $cat->name ) . '</a>';
$output .= '<span class="breadcrumb-separator" aria-hidden="true">/</span>';
} else {
$output .= '<span class="breadcrumb-current">' . esc_html( $cat->name ) . '</span>';
}
$output .= '</li>';
}
$output .= '</ol>';
$output .= '</nav>';
return $output;
}
Exemplo de Uso com Marcação Schema.org
Para SEO avançado, adicione dados estruturados:
/**
* Gera trilha breadcrumb com markup Schema.org JSON-LD
*
* @param int|null $post_id ID do post
* @return string HTML + Script JSON-LD
*/
function wppoland_get_breadcrumb_with_schema( $post_id = null ) {
if ( ! $post_id ) {
$post_id = get_the_ID();
}
$categories = get_the_category( $post_id );
if ( empty( $categories ) ) {
return '';
}
$category = $categories[0];
$trail = array();
// Construir trilha de categorias
while ( $category->parent ) {
$category = get_category( $category->parent );
array_unshift( $trail, $category );
}
array_unshift( $trail, get_category( $categories[0]->term_id ) );
// Construir array para Schema.org
$schema_items = array();
// Homepage como primeiro item
$schema_items[] = array(
'@type' => 'ListItem',
'position' => 1,
'name' => 'Início',
'item' => home_url( '/' )
);
// Categorias
$position = 2;
foreach ( $trail as $cat ) {
$schema_items[] = array(
'@type' => 'ListItem',
'position' => $position,
'name' => $cat->name,
'item' => get_category_link( $cat->term_id )
);
$position++;
}
// Post atual (último item)
$schema_items[] = array(
'@type' => 'ListItem',
'position' => $position,
'name' => get_the_title( $post_id ),
'item' => get_permalink( $post_id )
);
// Gerar JSON-LD
$schema = array(
'@context' => 'https://schema.org',
'@type' => 'BreadcrumbList',
'itemListElement' => $schema_items
);
// Gerar HTML
$html = wppoland_get_full_category_trail( $post_id );
// Adicionar JSON-LD
$html .= '<script type="application/ld+json">';
$html .= json_encode( $schema, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES );
$html .= '</script>';
return $html;
}
Usar get_category_parents(): Função Nativa do WordPress
O WordPress oferece uma função nativa para obter a hierarquia de categorias:
/**
* Usa get_category_parents() para obter hierarquia
*
* @param int $category_id ID da categoria
* @param bool $link Se true, inclui links HTML
* @param string $separator Separador entre categorias
* @param bool $nicename Se true, usa nice name
* @param array $visited Array de categorias já visitadas
* @return string Hierarquia de categorias
*/
$parents = get_category_parents( $category_id, true, ' » ', true );
// Exemplo completo com wrapper:
function wppoland_get_parents_wrapper() {
$categories = get_the_category();
if ( ! empty( $categories ) ) {
$category = $categories[0];
$parents = get_category_parents( $category->term_id, true, ' » ', true );
// Adicionar classes CSS
$parents = str_replace(
'<a href=',
'<a class="breadcrumb-link" href=',
$parents
);
return '<div class="category-parents">' . $parents . '</div>';
}
return '';
}
Obter Posts por Categoria com WP_Query
Quando você precisa exibir posts de uma categoria e suas subcategorias:
/**
* Obtém posts de uma categoria e todas as suas subcategorias
*
* @param int|string $category Categoria por ID ou slug
* @param int $posts_per_page Número de posts
* @return WP_Query Resultado da query
*/
function wppoland_get_posts_in_category_and_children( $category, $posts_per_page = 10 ) {
// Se for slug, obter ID
if ( is_string( $category ) ) {
$cat = get_category_by_slug( $category );
if ( $cat ) {
$category = $cat->term_id;
}
}
// Obter todas as subcategorias
$subcategories = get_categories( array(
'child_of' => $category,
'fields' => 'ids',
'hide_empty' => false
) );
// Incluir a categoria principal
$all_categories = array_merge( array( $category ), $subcategories );
// Query de posts
$query = new WP_Query( array(
'category__in' => $all_categories,
'posts_per_page' => $posts_per_page,
'orderby' => 'date',
'order' => 'DESC',
'ignore_sticky_posts' => true
) );
return $query;
}
// Uso:
$query = wppoland_get_posts_in_category_and_children( 'tecnologia', 5 );
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
// Exibir post
}
wp_reset_postdata();
}
Exibir Apenas Categorias com Posts
Para verificar se uma categoria tem posts antes de exibi-la:
/**
* Verifica se categoria tem posts (incluindo subcategorias)
*
* @param int $category_id ID da categoria
* @return bool True se tem posts
*/
function wppoland_category_has_posts( $category_id ) {
$category = get_category( $category_id );
// Verificar posts na categoria
if ( $category->count > 0 ) {
return true;
}
// Verificar posts nas subcategorias
$subcategories = get_categories( array(
'child_of' => $category_id,
'hide_empty' => false,
'fields' => 'ids'
) );
foreach ( $subcategories as $sub_id ) {
$sub = get_category( $sub_id );
if ( $sub->count > 0 ) {
return true;
}
}
return false;
}
/**
* Lista categorias com posts visíveis
*
* @return string HTML da lista
*/
function wppoland_list_active_categories() {
$categories = get_categories( array(
'hide_empty' => true,
'parent' => 0, // Apenas categorias raiz
'orderby' => 'name',
'order' => 'ASC'
) );
if ( empty( $categories ) ) {
return '';
}
$output = '<ul class="active-categories">';
foreach ( $categories as $cat ) {
if ( wppoland_category_has_posts( $cat->term_id ) ) {
$link = get_category_link( $cat->term_id );
$output .= '<li><a href="' . esc_url( $link ) . '">';
$output .= esc_html( $cat->name );
$output .= '<span class="post-count">(' . intval( $cat->count ) . ')</span>';
$output .= '</a></li>';
}
}
$output .= '</ul>';
return $output;
}
Categorias Personalizadas e Taxonomias
O sistema funciona da mesma forma para taxonomias personalizadas:
/**
* Obtém hierarquia para qualquer taxonomia
*
* @param string $taxonomy Nome da taxonomia
* @param int $term_id ID do termo
* @return string HTML da hierarquia
*/
function wppoland_get_term_hierarchy( $taxonomy, $term_id ) {
$term = get_term( $term_id, $taxonomy );
if ( is_wp_error( $term ) || ! $term ) {
return '';
}
$trail = array();
$current = $term;
// Percorrer hierarquia
while ( $current->parent ) {
$current = get_term( $current->parent, $taxonomy );
array_unshift( $trail, $current );
}
// Adicionar termo atual
array_unshift( $trail, $term );
// Construir HTML
$output = '<nav class="term-breadcrumb">';
foreach ( $trail as $index => $t ) {
$is_last = ( $index === count( $trail ) - 1 );
if ( ! $is_last ) {
$link = get_term_link( $t, $taxonomy );
$output .= '<a href="' . esc_url( $link ) . '">' . esc_html( $t->name ) . '</a>';
$output .= ' » ';
} else {
$output .= '<span class="current">' . esc_html( $t->name ) . '</span>';
}
}
$output .= '</nav>';
return $output;
}
// Uso para taxonomia personalizada:
$hierarchy = wppoland_get_term_hierarchy( 'produto_categoria', $term_id );
Categorias com Múltiplos Posts
Quando um post pertence a múltiplas categorias, você pode permitir que o utilizador escolha qual exibir:
/**
* Exibe seletor de categorias para posts com múltiplas categorias
*
* @param int|null $post_id ID do post
*/
function wppoland_category_selector( $post_id = null ) {
if ( ! $post_id ) {
$post_id = get_the_ID();
}
$categories = get_the_category( $post_id );
if ( count( $categories ) <= 1 ) {
// Se só tem uma categoria, exibir normalmente
echo wppoland_get_full_category_trail( $post_id );
return;
}
// Múltiplas categorias - exibir seletor
?>
<div class="multi-category-selector">
<label for="category-select">Ver em:</label>
<select id="category-select" onchange="window.location.href=this.value">
<?php foreach ( $categories as $cat ) : ?>
<option value="<?php echo esc_url( get_category_link( $cat->term_id ) ); ?>">
<?php echo esc_html( $cat->name ); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<?php
}
Dicas de Performance e Otimização
Cache de Categorias
Para sites com muito tráfego, implemente cache:
/**
* Obtém hierarquia com cache transient
*
* @param int $post_id ID do post
* @param int $cache_time Tempo de cache em segundos (padrão: 1 hora)
* @return string HTML da hierarquia
*/
function wppoland_get_cached_category_hierarchy( $post_id = null, $cache_time = 3600 ) {
if ( ! $post_id ) {
$post_id = get_the_ID();
}
// Gerar chave de cache única
$cache_key = 'cat_hierarchy_' . $post_id . '_' . get_current_blog_id();
// Tentar obter do cache
$cached = get_transient( $cache_key );
if ( false !== $cached ) {
return $cached;
}
// Gerar hierarquia
$hierarchy = wppoland_get_full_category_trail( $post_id );
// Salvar no cache
set_transient( $cache_key, $hierarchy, $cache_time );
return $hierarchy;
}
// Uso - substitua a chamada original
$hierarchy = wppoland_get_cached_category_hierarchy();
Evitar Consultas Excessivas
Quando precisar de múltiplas categorias, use uma única consulta:
/**
* Otimizado: Obtém hierarquias para múltiplos posts
* Evita N+1 queries
*
* @param array $post_ids Array de IDs de posts
* @return array Array com post_id => hierarquia HTML
*/
function wppoland_get_multiple_category_hierarchies( $post_ids ) {
if ( empty( $post_ids ) ) {
return array();
}
// Obter todas as categorias de uma vez
$all_categories = get_the_category( $post_ids );
// Organizar por post
$categories_by_post = array();
foreach ( $all_categories as $cat ) {
if ( ! isset( $categories_by_post[ $cat->post_id ] ) ) {
$categories_by_post[ $cat->post_id ] = array();
}
$categories_by_post[ $cat->post_id ][] = $cat;
}
// Gerar hierarquias
$hierarchies = array();
foreach ( $post_ids as $post_id ) {
if ( isset( $categories_by_post[ $post_id ] ) ) {
$categories = $categories_by_post[ $post_id ];
$category = $categories[0];
// Gerar hierarquia (código simplificado)
$trail = array();
while ( $category->parent ) {
$category = get_category( $category->parent );
array_unshift( $trail, $category );
}
array_unshift( $trail, get_category( $categories[0]->term_id ) );
// Construir HTML
$html = '';
foreach ( $trail as $cat ) {
$html .= '<a href="' . esc_url( get_category_link( $cat->term_id ) ) . '">';
$html .= esc_html( $cat->name ) . '</a> / ';
}
$hierarchies[ $post_id ] = rtrim( $html, ' / ' );
}
}
return $hierarchies;
}
FAQ – Perguntas Frequentes
Como exibir a categoria atual destacada?
Use CSS para estilizar o último item:
.breadcrumb-trail .breadcrumb-item:last-child .breadcrumb-current {
color: #333;
}
Posso usar isso em páginas de arquivo?
Sim, em arquivos de categoria você pode exibir o caminho completo:
// Em category.php
if ( is_category() ) {
$current_cat = get_queried_object();
if ( $current_cat->parent ) {
$parent = get_category( $current_cat->parent );
echo 'Você está em: <a href="' . get_category_link( $parent->term_id ) . '">';
echo esc_html( $parent->name ) . '</a> / ';
}
echo '<strong>' . esc_html( $current_cat->name ) . '</strong>';
}
Como obter apenas a categoria pai, ignorando a atual?
function wppoland_get_parent_category_only() {
$categories = get_the_category();
if ( ! empty( $categories ) && $categories[0]->parent ) {
$parent = get_category( $categories[0]->parent );
return $parent;
}
return false;
}
O código funciona com categorias em outras línguas?
Sim, desde que o WordPress esteja configurado para multilingual. Use get_category() que retorna os dados na língua atual do site.
Como verificar se duas categorias são relacionadas (pai/filho)?
// Método 1: Usando cat_is_ancestor_of()
$is_child = cat_is_ancestor_of( $potential_child_id, $potential_parent_id );
// Método 2: Comparando IDs diretamente
$child_category = get_category( $child_id );
$is_child = ( $child_category->parent === $parent_id );
Resumo e Checklist de Implementação
Implementação Básica
- Adicionar função
wppoland_get_category_hierarchy()ao functions.php - Inserir chamada no template onde deseja exibir
- Adicionar CSS para estilização
Implementação Avançada
- Usar
wppoland_get_full_category_trail()para hierarquias completas - Adicionar markup Schema.org para SEO
- Implementar cache com transients
Otimização
- Para sites com muito tráfego, usar cache agressivo
- Em loops, usar consultas otimizadas
- Minimizar chamadas get_category() em loops
Boas Práticas
- Sempre usar
esc_url()eesc_html()para segurança - Verificar se categorias existem antes de usar
- Testar com posts em múltiplos níveis de hierarquia
- Validar markup HTML
Com estas técnicas, você pode criar sistemas de navegação por categorias robustos e otimizados para qualquer projeto WordPress.

