add_filter( 'wp_get_nav_menu_items', 'wpcb_add_product_subcats_to_menu' ); if ( ! function_exists( 'wpcb_add_product_subcats_to_menu' ) ) { /** * wpcb_add_product_subcats_to_menu. * * @see https://wpcodebook.com/snippets/automatically-add-woocommerce-product-subcategories-to-categories-in-menu/ */ function wpcb_add_product_subcats_to_menu( $items ) { if ( is_admin() ) { return $items; } $children_order = count( $items ) + 1; foreach ( $items as $item ) { $items = wpcb_process_menu_item( $item, $items, $children_order ); } return $items; } } if ( ! function_exists( 'wpcb_process_menu_item' ) ) { /** * wpcb_process_menu_item. */ function wpcb_process_menu_item( $item, $items, &$children_order ) { if ( 'product_cat' === $item->object ) { $children = get_terms( array( 'taxonomy' => 'product_cat', 'hide_empty' => false, 'parent' => $item->object_id, 'limit' => -1, 'orderby' => 'title', 'order' => 'ASC', ) ); if ( ! empty( $children ) && ! is_wp_error( $children ) ) { foreach ( $children as $child ) { $tmp_item = new stdClass(); $tmp_item->ID = 100000 + $children_order; $tmp_item->post_author = $item->post_author; $tmp_item->post_date = ''; $tmp_item->post_date_gmt = ''; $tmp_item->post_content = ''; $tmp_item->post_title = ''; $tmp_item->post_excerpt = ''; $tmp_item->post_status = 'publish'; $tmp_item->comment_status = ''; $tmp_item->ping_status = ''; $tmp_item->post_password = ''; $tmp_item->post_name = $child->name; $tmp_item->to_ping = ''; $tmp_item->pinged = ''; $tmp_item->post_modified = ''; $tmp_item->post_modified_gmt = ''; $tmp_item->post_content_filtered = ''; $tmp_item->post_parent = 0; $tmp_item->guid = ''; $tmp_item->menu_order = $children_order; $tmp_item->post_type = 'nav_menu_item'; $tmp_item->post_mime_type = ''; $tmp_item->comment_count = ''; $tmp_item->filter = 'raw'; $tmp_item->db_id = $tmp_item->ID; $tmp_item->menu_item_parent = $item->ID; $tmp_item->object_id = $child->term_id; $tmp_item->object = 'product_cat'; $tmp_item->type = 'taxonomy'; $tmp_item->type_label = ''; $tmp_item->url = get_term_link( $child->term_id ); $tmp_item->title = $child->name; $tmp_item->target = ''; $tmp_item->attr_title = ''; $tmp_item->description = ''; $tmp_item->classes = array( 0 => '' ); $tmp_item->xfn = ''; $items[] = $tmp_item; $children_order++; $items = wpcb_process_menu_item( $tmp_item, $items, $children_order ); } } } return $items; } }
7 thoughts on “Automatically add WooCommerce product subcategories to categories in menu”
Leave a Comment
You must be logged in to post a comment.
Thanks for the snippet.
But how could it be to have the full categories tree and not just the first level?
Hi Nadia,
Happy to help 🙂
I’ve just updated the snippet for you – now it will include the full categories tree.
Please give it a try and let me know what you think.
Thanks a lot! But it is not working as expected.
With the previous snipped I had several menu items (shop and not), In one of that I had Man And Woman as shop categories and the snipped populated the links UNDER Man and Women with the first level categories.
Now as a test I created a custom link “test”, inside it I placed the shop category “woman” and I expected to see something like
– menu link 1
– menu link 2
– test
– – woman
– – – t-shirt
– – – sweaters
and so on.
While I had directly all the sub categories, with no nidification, in the first level of the menu (deleting the word “test”). Moreover, I applied a CSS to “test” to hide it in test mode, but the class was missing.
The result is:
– menu link 1
– menu link 2
– t-shirt
– sweaters
Thanks
Hi Nadia,
I wasn’t able to reproduce the issue as you’ve described, however, I did find a bug when a category is displayed in the menu several times. Fixed it by replacing:
with:
I’ve updated the snippet. Please give it a try and let me know if that helped.
Regarding “… the class was missing…” – not sure if I got it correctly, but you can add a class to your menu items by replacing:
with:
Hope this helps. Please let me know if you have any questions.
sorry, haven’t been back.
Thanks with your update it works fine but there is still an issue:
if I have this menu (product categories are under the first menu voice “abbigliamento”
https://snipboard.io/oTXU02.jpg
the last two items doesn’t exist in front end (no in the html code),
while if i switch the menu items in this way (not collapsed version, but I only switched the position of the last three items):
https://snipboard.io/6t9gvs.jpg
it works but not logged users don’t see the last item in the submenu “world”.
If it may help, I have several voices disabled for logged in users and other for not logged in users.
and the last one, in submenu “world” is activated only for not logged users (but it doesn’t work).
If I disable your snippet, all works fine.
Thanks!
Nadia
hello, how we can change the code in order to select the level we want subcategories to be displayed?
for example in this menu
top
-submenu
–subsubmenu
if i select 1 level to show only top, if i select 2 to show top and submenu, is this possible? thanks
Hi,
Yes, that’s possible.
Add this code to the
wpcb_process_menu_item()
function, right after theif ( 'product_cat' === $item->object ) {
line:* replace
2
with the level you need.I hope this helps. Let me know if you have any questions.