So one of our clients uses an ERP in order to update the products of woocomerce in his wordpress website. The ERP is updating the database directly for everything regarding the products,categories,subcategories etc. Their only issue is that they want to create a menu item at the main menu and when they add a new category/subcategory or remove an existing to dynamically update that menu_item that will hold the product categories/sub-categories.

Is there any function that renders ALL the product categories as menus because the code I started implementing seems way an overkill.


global $wp_query;
global $wpdb;

$productToMenuHelper = new ProductToMenu();

$activeTemplateResult = $wpdb->get_results("SELECT * FROM `wp_options` where option_name='template'");
$activeTemplate = $activeTemplateResult[0]->option_value;

$templateOptionsResult = $wpdb->get_results("SELECT * FROM `wp_options` where option_name ='theme_mods_".$activeTemplate."'");

$templateOptions = $productToMenuHelper->unserializeOption($templateOptionsResult[0]->option_value);

$mainMenuId = $templateOptions["nav_menu_locations"]["top"];

$menuItems =  $wpdb->get_results("SELECT p.* 
  FROM wp_posts AS p 
  LEFT JOIN wp_term_relationships AS tr ON tr.object_id = p.ID
  LEFT JOIN wp_term_taxonomy AS tt ON tt.term_taxonomy_id = tr.term_taxonomy_id
 WHERE p.post_type = 'nav_menu_item' and tt.term_id={$mainMenuId}");

What Im trying to do is find the main menu from template, find all the menu items of that menu and after that get a payload of all product categories and subcategories and check if exist in the menu items payload

1 Answer 1


You could use the wp_get_nav_menu_items filter

add_filter('wp_get_nav_menu_items', 'prefix_add_categories_to_menu', 10, 3);

Then you could do something like this:

function prefix_add_categories_to_menu($items, $menu, $args) {
    // Make sure we only run the code on the applicable menu
    if($menu->slug !== 'replace_this' || is_admin()) return $items;

    // Get all the product categories
    $categories = get_categories(array(
        'taxonomy' => 'product_cat',
        'orderby' => 'name',
        'show_count' => 0,
        'pad_counts' => 0,
        'hierarchical' => 1,
        'hide_empty' => 1,
        'depth' => $depth,
        'title_li' => '',
        'echo' => 0 

    $menu_items = array();
    // Create menu items
    foreach($categories as $category) {
        $new_item = (object)array(
            'ID' => intval($category->term_id),
            'db_id' => intval($category->term_id),
            'menu_item_parent' => intval($category->category_parent),
            'post_type' => "nav_menu_item",
            'object_id' => intval($category->term_id),
            'object' => "product_cat",
            'type' => "taxonomy",
            'type_label' => __("Product Category", "textdomain"),
            'title' => $category->name,
            'url' => get_term_link($category),
            'classes' => array()
        array_push($menu_items, $new_item);
    $menu_order = 0;
    // Set the order property
    foreach ($menu_items as &$menu_item) {
        $menu_item->menu_order = $menu_order;

    return $menu_items;

You would create a menu in WordPress and then set the slug in the top of the function to make sure this only runs on the applicable menu. Then this function will replace any items in that menu with all of your product categories.

If you have a huge amount of categories i suggest caching this menu by using a transient, so that it only gets regenerated once a day for example.

  • it worked liked a charm! Thanks!
    – IseNgaRt
    Jun 13, 2019 at 13:05

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