phpwordpresswoocommercesubmenutaxonomy-terms

Sort WooCommerce product category sub menu items by name ASC in Wordpress menu


I am adding in my main WordPress menu to WooCommerce product category menu items, the children subcategory terms as submenu items with the following code and it works.

enter image description here

The code:

add_filter("wp_get_nav_menu_items", function ($items, $menu, $args) {

    // don't add child categories in administration of menus
    if (is_admin()) {
        return $items;
    }
    foreach ($items as $index => $i) {

        if ("product_cat" !== $i->object) {
            continue;
        }
        $term_children = get_term_children($i->object_id, "product_cat");
        // add child categories
        foreach ($term_children as $index2 => $child_id) {
            $child = get_term($child_id);
            $url = get_term_link($child);
            $e = new \stdClass();
            $e->title = $child->name;
            $e->url = $url;
            $e->menu_order = 500 * ($index + 1) + $index2;
            $e->post_type = "nav_menu_item";
            $e->post_status = "published";
            $e->post_parent = $i->ID;
            $e->menu_item_parent = $i->ID;
            $e->type = "custom";
            $e->object = "custom";
            $e->description = "";
            $e->object_id = 0;
            $e->db_id = 0;
            $e->ID = 0;
            $e->position = 0;
            $e->classes = array();
            $items[] = $e;
        }
    }

    return $items;

}, 10, 3); 

But I would like to sort that submenu items alphabetically in Ascending order and I didn't find a way to do it yet. How can I sort that submenu items by name (alphabetically) in Ascending order?


Solution

  • An additional foreach loop is required, to sort category sub menu items by name. Also there was some little oversights in your code (to avoid some errors). To finish you should always name your hooked functions for many different reasons.

    The revisited code:

    add_filter( 'wp_get_nav_menu_items', 'custom_submenu_product_categories', 10, 3 );
    function custom_submenu_product_categories( $items, $menu, $args ) {
        // don't add child categories in administration of menus
        if (is_admin()) {
            return $items;
        }
    
        $taxonomy = 'product_cat';
    
        foreach ($items as $index => $post) {
    
            if ( $taxonomy !== $post->object ) {
                continue;
            }
    
            $children_terms_ids = get_term_children( $post->object_id, $taxonomy );
            $unsorted_terms     = array(); // Initializing
    
            // Loop through children terms to prepare them to be sorted by name
            foreach ( $children_terms_ids as $child_id ) {
                $child_term = get_term( $child_id, $taxonomy );
    
                $unsorted_terms[$child_term->name] = $child_term; // Set each term in an array for sorting
            }
    
            ksort($unsorted_terms); // Sort menu sub-items by term name ASC
    
            $index2 = 0; // Initializing
    
            // Loop through sorted child terms to set them as sorted sub menu items
            foreach ( $unsorted_terms as $child_term_name => $child_term ) {
                $item = new \stdClass();
    
                $item->title            = $child_term_name;
                $item->url              = get_term_link( $child_term, $taxonomy );
                $item->menu_order       = 500 * ($index + 1) + $index2;
                $item->post_type        = 'nav_menu_item';
                $item->post_status      = 'published';
                $item->post_parent      = $post->ID;
                $item->menu_item_parent = $post->ID;
                $item->type             = 'custom';
                $item->object           = 'custom';
                $item->description      = '';
                $item->object_id        = 0;
                $item->db_id            = 0;
                $item->ID               = 0;
                $item->position         = 0;
                $item->classes          = array();
                $item->target           = ''; // <= Missing - Mandatory to avoid an error
                $item->xfn              = ''; // <= Missing - Mandatory to avoid an error
    
                $items[] = $item;
                $index2++;
            }
        }
        return $items;
    }
    

    Code goes in functions.php file of the active child theme (or active theme). Tested and works.