Как создать меню со всеми подкатегориями?
Это зависит от того, о каком именно меню идет речь:
1)
Если вы говорите о "пользовательских меню" (находятся в админке в разделе Дизайн -> Меню), вы можете сделать следующее:
Создать новую функцию с использованием хука
add_category
Внутри этой функции можно создать новый элемент типа записи меню, который будет правильно добавлен в ваше меню
Теперь при публикации новой категории пункт меню будет добавляться автоматически
Также следует добавить хук на удаление категории, чтобы поддерживать меню в актуальном состоянии
2)
Можно сделать гораздо проще без использования меню WordPress:
- Просто напишите функцию для вывода списка категорий (или используйте встроенную функцию
wp_list_categories
) - Если этого недостаточно, создайте кастомную функцию, которая (возможно рекурсивно) будет получать категории из базы данных
Для реализации первого варианта потребуются некоторые знания о работе WordPress.

Я предпочитаю использовать wp_list_categories
. Вот код, который я использовал в своем последнем проекте:
<?php wp_list_categories('orderby=ID&exclude=3,10,1,16,38&title_li=<span class="sidebar_heading d_shadow">' . __('Категории') . '</span>'); ?>
Вы получите список всех ваших категорий и подкатегорий.

После долгих исследований я нашел надежное и полезное решение. Этот класс отлично работает:
class EntexAutoSubmenu {
/**
* Конструктор
*/
function __construct(){
add_action('created_category', array($this, 'on_publish_category'));
}
/**
* При публикации новой дочерней категории добавляет её в соответствующее пользовательское меню.
*/
function on_publish_category($cat_id){
// Тема поддерживает пользовательские меню?
if (!current_theme_supports('menus')) return;
// У опубликованной таксономии есть родитель?
$cat = get_category($cat_id);
if (!$cat->category_parent) return;
$all_menus = get_terms('nav_menu', array('hide_empty' => true));
// Перебираем меню для поиска родительской страницы
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){
// Элемент уже в меню?
if ($menu_item->object_id == $cat_id) continue 2;
if ($menu_item->object_id == $cat->category_parent) $menu_parent = $menu_item;
}
// Добавляем новый элемент
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();

Другим вариантом может быть использование List Custom Taxonomy Widget, возможно, он подойдет для вашего случая (если вы не планируете использовать WP nav_menu).

Я написал собственный код для одного из своих клиентов
<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( '/' ) ); ?>">Главная</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>';
/* Второй запрос (без глобальной переменной) */
$query2 = new WP_Query( $args );
// Второй цикл
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;
// Восстановление оригинального запроса и данных поста
wp_reset_query();
wp_reset_postdata();
echo '</ul>';
echo '</li>';
}
?>
</ul>
</div>

Чтобы решить эту проблему, я попытался создать плагин, который автоматически создает пункт меню для опубликованной категории под ее родительской категорией, если она есть в меню.
Идея плагина:
1. В коде я использовал хук действия "created_$taxonomy".
2. Собрал все пункты меню (используя wp_get_nav_menu_items).
3. И добавил условие: если родитель опубликованной категории есть в пункте меню, то создается пункт меню как подменю родительской категории (используя wp_update_nav_menu_item).
<?php
/*
Plugin Name: Auto Category Submenu
Plugin URI:
Description: Создает пункт меню при публикации/создании категории, если её родительская категория есть в пункте меню.
Version: 0.1
Author: Mayank Gupta/Ravinder Kumar
Author URI:
License: GPL2
*/
class AutoSubmenu {
/**
* Конструктор
*/
function __construct() {
add_action( 'created_category', array( &$this, 'on_publish_cat' ) );
}
/**
* При публикации новой дочерней страницы добавляет её в соответствующее пользовательское меню.
*/
function on_publish_cat( $cat_id ) {
$cat = get_category( $cat_id );
//ID меню, в которых ваша родительская категория является пунктом меню
$menu_ids = array(101,100);
//получить все пункты меню
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; //все ID пунктов меню
}
}
//print_r($menu_terms_id); //тест пунктов меню
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();
Примечание: плагин выдает ошибку (заголовки уже отправлены) и пункт меню не создается при публикации категории. Возможно, это другая тема для обсуждения проблемы, но я поместил это здесь, потому что это может быть решением, если кто-то подскажет, где я ошибся. Извините, если я делаю что-то не так, размещая это здесь.

Я использую этот код для отображения всех категорий и подкатегорий в виде меню в моем проекте.
$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>";

Ответы обычно не ограничиваются блоками кода. Не могли бы вы отредактировать свой ответ и объяснить, что вы делаете и почему?

Вот мой подход, который работает для категорий товаров.
$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;
