6

Is it possible to create a menu with a category such that each time that I had a sub category that automatically display on the menu?

As far as I know, if I have a menu with the category "fruit", and I create the subcategory "bananas", I have to manually add it.

1
  • I would recommend JC Submenu from James Collings. Add new from WordPress plugins page. I is very simple to use and helpful. Just install, activate and select "JC Submemu" when adding a category in your main menu in your dashboard. May 4, 2017 at 16:51

8 Answers 8

3
+50

This depends on what kind of menu you are talking about:

1)

If you are talking about "custom menus" (found in the Backend under Design -> Menus) you can do the following:

  • Create a new function with the action hook add_category

  • inside of this function, you can create a new post of type the menu item type, which is added correctly to your menu

  • whenever a new category is published the menu item is added now

  • you should also hook into delete category, to keep your menu up-to-date

2)

You could do much easier without a wordpress menu:

  • just write a function to list your categories (or use the predefined wp_list_categories function)
  • if this is not sufficient write a customized one which (maybe
    recursivley) reads your categories from the database

For option 1 to code you require some knowledge about WordPress though.

2

I prefer using wp_list_categories. Here is my code I used in my last project:

<?php wp_list_categories('orderby=ID&exclude=3,10,1,16,38&title_li=<span class="sidebar_heading d_shadow">' . __('Categories') . '</span>'); ?>

You will get a list of all your categories and sub-categories.

2

After many research I found a trustful useful solution, this class works well:

class EntexAutoSubmenu {

    /**
     * Constructor
     */
    function __construct(){
        add_action('created_category', array($this, 'on_publish_category'));
    }

    /**
     * When publishing a new child category, add it to the appropriate custom menu.
     */
    function on_publish_category($cat_id){

        // Theme supports custom menus?
        if (!current_theme_supports('menus')) return;

        // Published taxonomy has parent?
        $cat = get_category($cat_id);
        if (!$cat->category_parent) return;

        $all_menus = get_terms('nav_menu', array('hide_empty' => true));

        // Loop through the menus to find page parent
        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){
                // Item already in menu?
                if ($menu_item->object_id == $cat_id) continue 2;
                if ($menu_item->object_id == $cat->category_parent) $menu_parent = $menu_item;
            }

            // Add new 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();
1

Another alternative would be to use List Custom Taxonomy Widget, it might work in your use case (if you are not planning to use WP nav_menu).

1

To solve this problem i tried to create a plugin which automatically create menu item for publish category under it's parent category if in menu.

Idea for plugin:

1.in code, i used "created_$taxonomy" action hook.

2.collect all the menu item ( by using wp_get_nav_menu_items)

3.and put condition if parent of publish category lies in menu-item than a menu-item created as sub menu of it's parent category.(by using wp_update_nav_menu_item)

<?php
/*
Plugin Name: Auto Category Submenu
Plugin URI: 
Description: Create menu item when category publish/create if it's parent category in menu item.
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' ) );
    }

    /**
     * When publishing a new child page, add it to the appropriate custom menu.
     */
    function on_publish_cat( $cat_id ) {
        $cat = get_category( $cat_id );

        //menu id for you menus in which your sub-category's parent category as menu item 
        $menu_ids = array(101,100);

        //retrieve all meu items from menu
        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; //all menu items id
            }
        }
        //print_r($menu_terms_id); //test for items in menu
        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();

Note: plugin giving error (header already sent) and menu item not created when category publish.This may be another topic for problem but i put it here because this may be a solution if some suggest me where i am wrong.Sorry if i'm doing something wrong by putting it here

1

I coded my own for one my of clients

<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( '/' ) ); ?>">home</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>';

            /* The 2nd Query (without global var) */
            $query2 = new WP_Query( $args );
            // The 2nd Loop
            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;

            // Restore original Query & Post Data
            wp_reset_query();
            wp_reset_postdata();
            echo '</ul>';
        echo '</li>';
        }
    ?>
  </ul>
</div>
2
  • dont think you closed div class menu
    – Jon
    Feb 9, 2014 at 14:26
  • get_all_category_ids() is deprecated now Jan 9, 2023 at 12:16
0

i am using to show all category and sub category of category as a menu in my project.

$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>";
2
  • 1
    Answers are usually more than blocks of code. Could you please edit your answer and explain what you're doing and why?
    – Howdy_McGee
    Jun 1, 2017 at 14:30
  • This code doesn't compile or work, and it is also dependent on WooCommerce. Mar 16, 2019 at 19:47
0

this is my approach, this works for product categories.

$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;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.