¿Cómo crear un menú con todas las subcategorías?
Esto depende del tipo de menú al que te refieras:
1)
Si estás hablando de "menús personalizados" (encontrados en el Backend bajo Diseño -> Menús) puedes hacer lo siguiente:
Crea una nueva función con el hook de acción
add_category
dentro de esta función, puedes crear un nuevo post del tipo de elemento de menú, el cual se añadirá correctamente a tu menú
cuando se publique una nueva categoría, el elemento del menú se añadirá automáticamente
también deberías engancharte al hook de borrado de categorías, para mantener tu menú actualizado
2)
Podrías hacerlo mucho más fácil sin un menú de WordPress:
- simplemente escribe una función para listar tus categorías (o usa la función predefinida
wp_list_categories
) - si esto no es suficiente, escribe una personalizada que (quizás
recursivamente) lea tus categorías desde la base de datos
Para la opción 1 necesitarás cierto conocimiento sobre WordPress.

Prefiero usar wp_list_categories
. Aquí está el código que usé en mi último proyecto:
<?php wp_list_categories('orderby=ID&exclude=3,10,1,16,38&title_li=<span class="sidebar_heading d_shadow">' . __('Categorías') . '</span>'); ?>
Obtendrás una lista de todas tus categorías y subcategorías.

Después de mucha investigación encontré una solución confiable y útil, esta clase funciona bien:
class EntexAutoSubmenu {
/**
* Constructor
*/
function __construct(){
add_action('created_category', array($this, 'on_publish_category'));
}
/**
* Cuando se publica una nueva categoría hija, se agrega al menú personalizado correspondiente.
*/
function on_publish_category($cat_id){
// ¿El tema soporta menús personalizados?
if (!current_theme_supports('menus')) return;
// ¿La taxonomía publicada tiene padre?
$cat = get_category($cat_id);
if (!$cat->category_parent) return;
$all_menus = get_terms('nav_menu', array('hide_empty' => true));
// Recorrer los menús para encontrar el padre de página
foreach ($all_menus as $menu) {
$menu_parent = NULL;
$menu_items = wp_get_nav_menu_items($menu->term_id, array('post_status' => 'publish,draft'));
if (!is_array($menu_items)) continue;
foreach ($menu_items as $menu_item){
// ¿El ítem ya está en el menú?
if ($menu_item->object_id == $cat_id) continue 2;
if ($menu_item->object_id == $cat->category_parent) $menu_parent = $menu_item;
}
// Agregar nuevo ítem
if ($menu_parent) {
wp_update_nav_menu_item($menu->term_id, 0, array(
'menu-item-object-id' => $cat_id,
'menu-item-object' => $cat->taxonomy,
'menu-item-parent-id' => $menu_parent->ID,
'menu-item-type' => 'taxonomy',
'menu-item-status' => 'publish'
));
}
}
}
}
$auto_submenu = new EntexAutoSubmenu();

Otra alternativa sería usar List Custom Taxonomy Widget, podría funcionar en tu caso de uso (si no planeas usar el menú de navegación de WP).

Programé el mío propio para uno de mis clientes
<div class="menu">
<ul id="MenuBar1" class="MenuBarHorizontal">
<li><a <?PHP if( count($_GET) == 0 ){ echo 'class="-current"';} ?> href="<?php echo esc_url( home_url( '/' ) ); ?>">inicio</a></li>
<?php
$category_ids = get_all_category_ids();
sort($category_ids);
foreach($category_ids as $cat_id) {
$cat_name = get_cat_name($cat_id);
echo '<li><a href="' . get_category_link( $cat_id ) . '">' . $cat_name . '</a>';
$args = array( 'numberposts' => -1, 'offset'=> 0, 'cat' => $cat_id, 'orderby' => 'ID', 'order' => 'ASCE' );
echo '<ul>';
/* La segunda consulta (sin variable global) */
$query2 = new WP_Query( $args );
// El segundo bucle
while( $query2->have_posts() ):
$query2->next_post();
echo '<li><a href="' . get_permalink( $query2->post->ID ) . '">' . get_the_title( $query2->post->ID ) . '</a></li>';
endwhile;
// Restaurar la consulta original y los datos del post
wp_reset_query();
wp_reset_postdata();
echo '</ul>';
echo '</li>';
}
?>
</ul>
</div>

Para resolver este problema, intenté crear un plugin que automáticamente cree un elemento de menú para la categoría publicada bajo su categoría padre si está en el menú.
Idea para el plugin:
1. En el código, utilicé el gancho de acción "created_$taxonomy".
2. Recopilar todos los elementos del menú (usando wp_get_nav_menu_items).
3. Y establecer la condición de que si el padre de la categoría publicada está en el elemento del menú, entonces se crea un elemento del menú como submenú de su categoría padre (usando wp_update_nav_menu_item).
<?php
/*
Plugin Name: Auto Category Submenu
Plugin URI:
Description: Crea un elemento de menú cuando se publica/crea una categoría si su categoría padre está como elemento del menú.
Version: 0.1
Author: Mayank Gupta/Ravinder Kumar
Author URI:
License: GPL2
*/
class AutoSubmenu {
/**
* Constructor
*/
function __construct() {
add_action( 'created_category', array( &$this, 'on_publish_cat' ) );
}
/**
* Al publicar una nueva página hija, añadirla al menú personalizado correspondiente.
*/
function on_publish_cat( $cat_id ) {
$cat = get_category( $cat_id );
// IDs de menú en los que la categoría padre del subcategoría es un elemento del menú
$menu_ids = array(101,100);
// Recuperar todos los elementos del menú
foreach($menu_ids as $menu_id){
$menu_items[] = wp_get_nav_menu_items( $menu_id, array('post_status' => 'publish','post_type' => 'nav_menu_item','output' => ARRAY_A, ) );
}
foreach($menu_items as $menu_item){
$counter = 0 ;
echo'<!--';
print_r($menu_item);
echo'-->';
foreach($menu_item as $menu_term){
$menu_terms_id[] = $menu_term->object_id; // Todos los IDs de elementos del menú
}
}
//print_r($menu_terms_id); // Prueba para elementos en el menú
foreach( $menu_terms_id as $menu_term ){
if( $cat->category_parent == $menu_term){
wp_update_nav_menu_item( $cat_id, 0, array(
'menu-item-object-id' => $cat_id,
'menu-item-object' => $cat->taxonomy,
'menu-item-parent-id' => $menu_term,
'menu-item-type' => 'category',
'menu-item-status' => 'publish'
) );
}else{
return;
}
}
}
}
$auto_submenu = new AutoSubmenu();
Nota: El plugin está dando error (encabezado ya enviado) y no se crea el elemento del menú cuando se publica la categoría. Esto podría ser otro tema para el problema, pero lo pongo aquí porque podría ser una solución si alguien me indica dónde estoy equivocado. Disculpen si hago algo mal al ponerlo aquí.

Estoy utilizando esto para mostrar todas las categorías y subcategorías de una categoría como un menú en mi proyecto.
$all_categories = get_categories( $args );
echo "<div class='container'>";
echo "<div class='productsubmenu'>";
echo "<ul>";
foreach ($all_categories as $cat)
{
if($cat->category_parent == 0)
{
$category_id = $cat->term_id;
$thumbnail_id = get_woocommerce_term_meta( $cat->term_id, 'thumbnail_id', true );
$image = wp_get_attachment_url( $thumbnail_id );
echo '<li class="parent '.$my.' "><a href="'.get_term_link( $cat ) . '">'.$cat->name.'</a>';
$args2 = array(
'taxonomy' => $taxonomy,
'child_of' => 0,
'parent' => $category_id,
'orderby' => $orderby,
'show_count' => $show_count,
'pad_counts' => $pad_counts,
'hierarchical' => $hierarchical,
'title_li' => $title,
'hide_empty' => $empty
);
$args = array(
'hierarchical' => 1,
'show_option_none' => '',
'hide_empty' => 0,
'parent' => $parent_cat_ID,
'taxonomy' => 'product_cat'
);
$subcats = get_categories($args2);
echo '<ul class="wooc_sclist">';
foreach ($subcats as $sc) {
}
$link = get_term_link( $sc->slug, $sc->taxonomy );
echo '<li class="'.$my.'" ><a href="'. $link .'">'.$sc->name.'</a></li>';
}
echo '</ul>';
echo "</li>";
}
else
{
}
}
echo "</ul>";
echo "</div>";
echo "</div>";

Las respuestas suelen ser más que bloques de código. ¿Podrías por favor editar tu respuesta y explicar qué estás haciendo y por qué?

este es mi enfoque, esto funciona para categorías de productos.
$cat_args = array( 'orderby' => 'name', 'order' => 'asc', 'hide_empty' => true,);
$cats = get_terms( 'product_cat', $cat_args );
foreach ($cats as $key => $cat):
if ($cat->parent == 0):
echo $cat->name;
foreach ($cats as $key => $cat2):
if ($cat2->parent == $cat->term_id):
echo $cat2->name;
foreach ($cats as $key => $cat3):
if ($cat3->parent == $cat2->term_id):
echo $cat3->name;
endif;
endforeach;
endif;
endforeach;
endif;
endforeach;
