Mostrar categorías y subcategorías con sus posts en WordPress
Básicamente como dice el título, quiero obtener una lista de categorías y subcategorías y luego los posts (con enlaces) para esas categorías/subcategorías.
Esta es la estructura que estoy tratando de lograr:
- Categoría 1
- Subcategoría 1 dentro de categoría 1
- Post 1 dentro de subcategoría 1
- Post 2 dentro de subcategoría 1
- Post 3 dentro de subcategoría 1
- Subcategoría 2 dentro de categoría 1
- Post 1 dentro de subcategoría 2
- Post 2 dentro de subcategoría 2
- Post 3 dentro de subcategoría 2
- Subcategoría 3 dentro de categoría 1
- Post 1 dentro de subcategoría 3
- Post 2 dentro de subcategoría 3
- Post 3 dentro de subcategoría 3
- Posts que no tienen subcategoría
- Post 1 sin subcategoría
- Post 1 sin subcategoría
- Categoría 2
- Subcategoría 1 dentro de categoría 2
- Post 1 dentro de subcategoría 1
- Post 2 dentro de subcategoría 1
- Post 3 dentro de subcategoría 1
- Subcategoría 2 dentro de categoría 2
- Post 1 dentro de subcategoría 2
- Post 2 dentro de subcategoría 2
- Post 3 dentro de subcategoría 2
- Subcategoría 3 dentro de categoría 2
- Post 1 dentro de subcategoría 2
- Post 2 dentro de subcategoría 2
- Post 3 dentro de subcategoría 2
- Posts que no tienen subcategoría
- Post 1 sin subcategoría
- Post 1 sin subcategoría
Hasta ahora, después de leer todo lo que pude encontrar sobre el tema, tengo el siguiente código:
<ul>
<?php
$get_parent_cats = array(
'parent' => '0' //obtener solo categorías de nivel superior
);
$all_categories = get_categories( $get_parent_cats ); //obtener categorías padre
foreach( $all_categories as $single_category ){
//para cada categoría, obtener el ID
$catID = $single_category->cat_ID;
echo '<li><a href=" ' . get_category_link( $catID ) . ' ">' . $single_category->name . '</a>'; //nombre y enlace de la categoría
$get_children_cats = array(
'child_of' => $catID //obtener hijos de este padre usando la variable catID
);
$child_cats = get_categories( $get_children_cats ); //obtener hijos de la categoría padre
echo '<ul class="children">';
foreach( $child_cats as $child_cat ){
//para cada subcategoría, obtener el ID
$childID = $child_cat->cat_ID;
//para cada subcategoría, mostrar el enlace y nombre
echo '<a href=" ' . get_category_link( $childID ) . ' ">' . $child_cat->name . '</a>';
}
echo '</ul></li>';
} //fin de la lógica de categorías ?>
</ul>
Este código muestra bien las categorías y subcategorías, pero necesito de alguna manera recorrer mis posts y mostrarlos dentro de las categorías/subcategorías. También he intentado usar el siguiente código:
<?php
// obtener todas las categorías de la base de datos
$cats = get_categories();
// recorrer las categorías
foreach ($cats as $cat) {
// configurar el ID de la categoría
$cat_id= $cat->term_id;
// Crear un encabezado para la categoría
echo "<h2>".$cat->name."</h2>";
// crear una consulta personalizada de WordPress
query_posts("cat=$cat_id&posts_per_page=100");
// comenzar el loop de WordPress!
if (have_posts()) : while (have_posts()) : the_post(); ?>
<?php // crear nuestro enlace ahora que el post está configurado ?>
<a href="<?php the_permalink();?>"><?php the_title(); ?></a>
<?php echo '<hr/>'; ?>
<?php endwhile; endif; // finalizar nuestro loop de WordPress. Comenzará de nuevo para cada categoría ?>
<?php } // finalizar la sentencia foreach ?>
</div><!-- #content -->
</div><!-- #container -->
Este código muestra todas las categorías y posts dentro de cada categoría, pero la estructura no es la que quiero. He estado tratando de combinar estos dos fragmentos de código durante dos días, pero nada de lo que intento me da el resultado que deseo. Soy inexperto con WordPress y realmente agradecería ayuda con esto.

Actualización: Código completo
<ul>
<?php
$get_parent_cats = array(
'parent' => '0' //obtener solo categorías de nivel superior
);
$all_categories = get_categories( $get_parent_cats );//obtener categorías padre
foreach( $all_categories as $single_category ){
//para cada categoría, obtener el ID
$catID = $single_category->cat_ID;
echo '<li><a href=" ' . get_category_link( $catID ) . ' ">' . $single_category->name . '</a>'; //nombre y enlace de la categoría
echo '<ul class="post-title">';
$query = new WP_Query( array( 'cat'=> $catID, 'posts_per_page'=>10 ) );
while( $query->have_posts() ):$query->the_post();
echo '<li><a href="'.get_the_permalink().'">'.get_the_title().'</a></li>';
endwhile;
wp_reset_postdata();
echo '</ul>';
$get_children_cats = array(
'child_of' => $catID //obtener hijos de este padre usando la variable catID
);
$child_cats = get_categories( $get_children_cats );//obtener hijos de la categoría padre
echo '<ul class="children">';
foreach( $child_cats as $child_cat ){
//para cada categoría hija, obtener el ID
$childID = $child_cat->cat_ID;
//para cada categoría hija, mostrar el enlace y nombre
echo '<a href=" ' . get_category_link( $childID ) . ' ">' . $child_cat->name . '</a>';
echo '<ul class="post-title">';
$query = new WP_Query( array( 'cat'=> $childID, 'posts_per_page'=>10 ) );
while( $query->have_posts() ):$query->the_post();
echo '<li><a href="'.get_the_permalink().'">'.get_the_title().'</a></li>';
endwhile;
wp_reset_postdata();
echo '</ul>';
}
echo '</ul></li>';
} //fin de la lógica de categorías ?>
</ul>

Hola Bikash, gracias por tu ayuda, pero necesito que los posts se muestren incluso si no hay subcategorías y también necesito que los posts tengan enlaces permanentes.

¿Quieres decir que no deseas mostrar los posts de categorías intermedias y solo los posts de la última categoría?

No, no, quiero mostrarlos, pero en caso de que no haya subcategorías, aún quiero mostrar los posts. Con el código que me diste, si tengo un post en la categoría padre no se muestra. Mira mi estructura y entenderás a lo que me refiero.

He creado una imagen para mostrarte lo que quiero decir. enlace como puedes ver en "kategorija3" los posts no se muestran porque no tengo subcategorías pero aún tengo posts en esa categoría. También tengo posts en "kategorija1" que no tienen subcategoría y tampoco se muestran.

si deseas mostrar los posts de la categoría padre y las categorías hijas en forma jerárquica, entonces debes usar el mismo bucle dentro del bucle foreach
padre también usa 'cat'=>$catID
en caso del bucle foreach
padre si quieres categorías nietas y más necesitas añadir más bucles foreach
anidados y wp_query

usa el mismo bucle antes de $get_children_cats = array(
'child_of' => $catID //obtener hijos de este padre usando la variable catID de antes
);
en tu código y usa 'cat' => $catID
esta vez

¿Podrías editar tu respuesta y darme el código completo? Estoy intentando implementar lo que dices pero estoy cometiendo algún error y no puedo hacer que funcione.

Continuemos esta discusión en el chat.

Esta función funciona inmediatamente, solo asegúrate de cambiar los nombres por tu propia taxonomía y tipo de post. Siéntete libre de leer los comentarios para mayor clarificación.
function ow_categories_with_subcategories_and_posts( $taxonomy, $post_type ) {
$taxonomy = $taxonomy;
$post_type = $post_type;
// Obtener las categorías principales que pertenecen a la taxonomía proporcionada (las que no tienen padre)
$categories = get_terms(
array(
'taxonomy' => $taxonomy,
'parent' => 0, // <-- Sin padre
'orderby' => 'term_id',
'hide_empty' => true // <-- cambiar a false para mostrar también las vacías
)
);
?>
<div>
<?php
// Iterar a través de todas las categorías para mostrar cada categoría individual
foreach ( $categories as $category ) {
$cat_name = $category->name;
$cat_id = $category->term_id;
$cat_slug = $category->slug;
// Mostrar el nombre de cada categoría individual
echo '<h3>Categoría: ' . $cat_name . ' - ID: ' . $cat_id . ' - Slug: ' . $cat_slug . '</h3>';
// Obtener todas las subcategorías que pertenecen a la categoría actual
$subcategories = get_terms(
array(
'taxonomy' => $taxonomy,
'parent' => $cat_id, // <-- El padre es la categoría actual
'orderby' => 'term_id',
'hide_empty' => true
)
);
?>
<div>
<?php
// Iterar a través de todas las subcategorías para mostrar cada subcategoría individual
foreach ( $subcategories as $subcategory ) {
$subcat_name = $subcategory->name;
$subcat_id = $subcategory->term_id;
$subcat_slug = $subcategory->slug;
// Mostrar el nombre de cada subcategoría individual con ID y Slug
echo '<h4>Subcategoría: ' . $subcat_name . ' - ID: ' . $subcat_id . ' - Slug: ' . $subcat_slug . '</h4>';
// Obtener todos los posts que pertenecen a esta subcategoría específica
$posts = new WP_Query(
array(
'post_type' => $post_type,
'posts_per_page' => -1, // <-- Mostrar todos los posts
'hide_empty' => true,
'order' => 'ASC',
'tax_query' => array(
array(
'taxonomy' => $taxonomy,
'terms' => $subcat_id,
'field' => 'id'
)
)
)
);
// Si hay posts disponibles dentro de esta subcategoría
if ( $posts->have_posts() ):
?>
<div>
<?php
// Mientras haya posts para mostrar
while ( $posts->have_posts() ): $posts->the_post();
// Mostrar el título de cada post con el ID del Post
?>
<p>Post: <?php the_title(); ?> - ID: <?php the_ID(); ?></p>
<?php
endwhile;
?>
</div>
<?php
else:
echo 'No se encontraron posts';
endif;
wp_reset_query();
}
?>
</div>
<?php
}
?>
</div>
<?php
}
ow_categories_with_subcategories_and_posts( 'el_nombre_de_tu_taxonomia', 'el_nombre_de_tu_tipo_de_post' );
