Auto Category Menu Sync自动分类菜单同步

让 WooCommerce 产品分类菜单同步,变得无比简单


你遇到过这个问题吗?

在 WordPress 后台编辑导航菜单时,当你从「产品分类」里批量添加多个分类到菜单中,你会发现——所有分类都变成了同级关系,没有任何父子层级。

即使你在「产品 → 产品分类」中已经正确设置了父子层级(如:珠宝 → 手链 → 卡地亚手链),添加到菜单后却变成:

text

JEWELRY & ACCESSORIES
BRACELET
Cartier Bracelet

而不是你想要的:

text

▼ JEWELRY & ACCESSORIES
    ▼ BRACELET
        Cartier Bracelet

你需要手动把每个子分类拖拽到父分类下方,一个个缩进调整。
如果你的产品分类有几十上百个,这项工作将耗费大量时间,甚至让人崩溃。

FTP 手动安装
在 /wp-content/plugins/ 目录下新建文件夹:auto-category-menu-sync

将插件代码保存为 auto-category-menu-sync.php

上传到 /wp-content/plugins/auto-category-menu-sync/ 目录

进入 WordPress 后台 → 插件 → 找到「Auto Category Menu Sync」→ 点击「启用」

解决方案:Auto Category Menu Sync 由QQ8111216原创,转载请声明。

这是一个专为 WooCommerce 设计的轻量级插件,它能自动将产品分类按正确的父子层级关系同步到导航菜单中,彻底告别手动拖拽。


核心功能

1️⃣ 一键同步,保留完整层级

选择目标菜单,点击「开始同步」,插件会自动:

  • 扫描所有 WooCommerce 产品分类
  • 识别每个分类的父级/子级关系
  • 按正确层级添加到菜单中(支持无限级嵌套)

2️⃣ 增量更新模式(防重复)

日常运营中,你可能会不断新增产品分类。再次同步时:

  • 只添加新增的分类
  • 已存在于菜单中的分类不会重复添加
  • 原有菜单顺序和自定义设置保持不变

3️⃣ 清空重建模式

当菜单结构混乱,或者你想完全重置时:

  • 勾选「清空现有菜单项」
  • 插件会先删除该菜单中的所有内容
  • 再重新添加全部分类(保持完整层级)

4️⃣ 完全兼容原生菜单编辑器

同步完成后,你依然可以在 外观 → 菜单 中:

  • 手动调整菜单项的顺序
  • 添加自定义链接、页面等
  • 设置菜单显示位置(顶部菜单、移动端菜单等)

插件不会锁定或覆盖你的手动调整。


使用场景

场景说明
新站搭建产品分类设置好后,一键生成完整的多级导航菜单
分类频繁新增每次新增子分类后,增量同步即可,无需重新搭建菜单
菜单结构重置勾选清空模式,一键恢复最干净的层级结构
大型分类目录几百个分类的场景下,手动拖拽几乎不可行,本插件是刚需

插件截图

界面说明
设置页面选择菜单、选择同步模式、点击按钮
同步前(菜单编辑界面)分类平铺、无层级
同步后(菜单编辑界面)父子层级完整显示、缩进正确

技术参数

项目说明
兼容性WordPress 5.0+ / WooCommerce 4.0+
多语言支持中文、英文(可扩展)
性能轻量级,无外部依赖,不拖慢后台
隐私不收集任何用户数据

常见问题

Q1:插件会影响前台菜单的显示效果吗?

A: 不会。插件只负责菜单的结构(哪个菜单项是父级、哪个是子级),不改变菜单的样式。前台菜单的显示效果由你的主题决定。

Q2:同步后我可以手动调整顺序吗?

A: 完全可以。同步只是帮你建立正确的父子层级,之后你可以像操作普通菜单一样随意拖拽调整。

Q3:如果我删除了某个产品分类,菜单会自动同步吗?

A: 不会自动删除。这是 WooCommerce 的设计机制——删除分类后,菜单中对应的菜单项会变成「(已删除)」状态,需要你手动移除。插件暂不涉及删除逻辑,避免误操作风险。

Q4:支持多级分类吗(父→子→孙→曾孙)?

A: 支持。理论上无限级嵌套,只要你在产品分类中正确设置了父子关系,插件就会原样同步到菜单中。

Q5:支持多站点(Multisite)吗?

A: 支持。每个站点独立管理自己的菜单和分类。

<?php
/**
 * Plugin Name: Auto Category Menu Sync Pro
 * Description: 自动将 WooCommerce 产品分类按层级关系同步到导航菜单中,支持按层级深度筛选(仅一级/二级/三级/全部分类)
 * Version: 2.0
 * Author: qq8111216
 */

if (!defined('ABSPATH')) {
    exit;
}

/**
 * 检查 WooCommerce 是否激活
 */
function acms_check_woocommerce() {
    if (!class_exists('WooCommerce')) {
        add_action('admin_notices', function() {
            echo '<div class="notice notice-error"><p>⚠️ Auto Category Menu Sync 插件需要安装并激活 <strong>WooCommerce</strong> 才能使用。</p></div>';
        });
        return false;
    }
    return true;
}

/**
 * 添加管理后台菜单页面
 */
add_action('admin_menu', 'acms_add_admin_menu');
function acms_add_admin_menu() {
    if (!class_exists('WooCommerce')) {
        return;
    }
    
    add_submenu_page(
        'themes.php',
        '分类菜单同步',
        '分类菜单同步',
        'manage_options',
        'auto-category-menu-sync',
        'acms_render_admin_page'
    );
}

/**
 * 渲染管理页面
 */
function acms_render_admin_page() {
    if (!class_exists('WooCommerce')) {
        echo '<div class="wrap"><div class="notice notice-error"><p>请先安装并激活 WooCommerce 插件。</p></div></div>';
        return;
    }
    
    // 处理表单提交
    if (isset($_POST['acms_sync_nonce']) && wp_verify_nonce($_POST['acms_sync_nonce'], 'acms_sync_action')) {
        $selected_menu_id = intval($_POST['menu_id']);
        $clear_existing = isset($_POST['clear_existing']);
        $depth = isset($_POST['depth']) ? intval($_POST['depth']) : 0;  // 0=全部, 1=一级, 2=二级, 3=三级
        
        $result = acms_sync_categories_to_menu($selected_menu_id, $clear_existing, $depth);
        
        if ($result === true) {
            $depth_text = acms_get_depth_text($depth);
            echo '<div class="notice notice-success is-dismissible"><p>✅ 同步成功!已添加 <strong>' . $depth_text . '</strong> 到菜单中。</p></div>';
        } elseif ($result === 'nothing_to_sync') {
            echo '<div class="notice notice-warning is-dismissible"><p>⚠️ 所选层级的分类已在菜单中,无需重复添加。</p></div>';
        } else {
            echo '<div class="notice notice-error is-dismissible"><p>❌ 同步失败,请检查是否选择了有效的菜单。</p></div>';
        }
    }
    
    $menus = wp_get_nav_menus();
    ?>
    <div class="wrap">
        <h1>自动分类菜单同步</h1>
        <p>将 WooCommerce 产品分类按<strong>父子层级关系</strong>自动添加到选定的导航菜单中。</p>
        
        <form method="post" action="">
            <?php wp_nonce_field('acms_sync_action', 'acms_sync_nonce'); ?>
            
            <table class="form-table">
                <tr>
                    <th scope="row"><label for="menu_id">选择目标菜单</label></th>
                    <td>
                        <select name="menu_id" id="menu_id" required>
                            <option value="">— 请选择 —</option>
                            <?php foreach ($menus as $menu): ?>
                                <option value="<?php echo esc_attr($menu->term_id); ?>">
                                    <?php echo esc_html($menu->name); ?>
                                </option>
                            <?php endforeach; ?>
                        </select>
                        <p class="description">选择要将产品分类添加到的菜单(例如:Main navigation)</p>
                    </td>
                </tr>
                
                <!-- 新增:层级深度选择 -->
                <tr>
                    <th scope="row"><label for="depth">同步层级</label></th>
                    <td>
                        <select name="depth" id="depth">
                            <option value="0">📁 所有层级(全部)</option>
                            <option value="1">📂 仅一级分类(顶级分类)</option>
                            <option value="2">📂 仅二级分类(子分类)</option>
                            <option value="3">📂 仅三级分类(孙分类)</option>
                        </select>
                        <p class="description">
                            选择要同步到菜单中的分类层级。<br>
                            <strong>例如:</strong>「仅一级分类」只会添加顶级分类,不会添加其子分类;「仅二级分类」只会添加第二层级的子分类。
                        </p>
                    </td>
                </tr>
                
                <tr>
                    <th scope="row"><label for="clear_existing">清空现有菜单项</label></th>
                    <td>
                        <input type="checkbox" name="clear_existing" id="clear_existing" value="1">
                        <label for="clear_existing">同步前先清空此菜单中的所有现有项目</label>
                        <p class="description">
                            ⚠️ 勾选后会删除该菜单中所有已有的菜单项,然后重新添加选层级的产品分类。<br>
                            <strong>不勾选时:</strong>只会添加菜单中尚不存在的分类,已有的会保留(不会重复添加)。
                        </p>
                    </td>
                </tr>
             </table>
            
            <p class="submit">
                <button type="submit" class="button button-primary" onclick="return confirm('确认要同步分类到菜单吗?');">
                    开始同步
                </button>
            </p>
        </form>
        
        <hr>
        
        <h2>层级说明</h2>
        <div style="background: #f5f5f5; padding: 15px; border-left: 4px solid #007cba;">
            <p><strong>📁 一级分类(顶级分类)</strong><br>
            例如:JEWELRY & ACCESSORIES</p>
            
            <p><strong>📂 二级分类(子分类)</strong><br>
            例如:BRACELET(隶属于 JEWELRY & ACCESSORIES)</p>
            
            <p><strong>📄 三级分类(孙分类)</strong><br>
            例如:Cartier Bracelet(隶属于 BRACELET)</p>
        </div>
        
        <h2>使用场景</h2>
        <ul>
            <li><strong>仅一级分类:</strong>适合简约导航,只显示大类,用户点击后进入分类页再筛选子类。</li>
            <li><strong>仅二级分类:</strong>适合作为某个顶级分类下的快速导航。</li>
            <li><strong>仅三级分类:</strong>适合精细化导航,直接展示最细粒度的产品分类。</li>
            <li><strong>所有层级:</strong>完整的多级下拉菜单,适合品类丰富的电商网站。</li>
        </ul>
        
        <p><strong>注意:</strong>同步后,你可以继续在 <code>外观 → 菜单</code> 中手动调整顺序或样式。</p>
    </div>
    <?php
}

/**
 * 获取层级文本描述
 */
function acms_get_depth_text($depth) {
    switch ($depth) {
        case 1: return '仅一级分类';
        case 2: return '仅二级分类';
        case 3: return '仅三级分类';
        default: return '所有层级分类';
    }
}

/**
 * 获取菜单中已有的所有产品分类ID
 */
function acms_get_existing_category_ids_in_menu($menu_id) {
    $existing_ids = [];
    $menu_items = wp_get_nav_menu_items($menu_id);
    
    if (!empty($menu_items)) {
        foreach ($menu_items as $item) {
            if ($item->type === 'taxonomy' && $item->object === 'product_cat') {
                $existing_ids[] = (int) $item->object_id;
            }
        }
    }
    
    return $existing_ids;
}

/**
 * 核心同步函数(支持层级筛选)
 *
 * @param int $menu_id 菜单ID
 * @param bool $clear_existing 是否清空
 * @param int $depth 层级深度:0=全部, 1=一级, 2=二级, 3=三级
 */
function acms_sync_categories_to_menu($menu_id, $clear_existing = false, $depth = 0) {
    if (!$menu_id) {
        return false;
    }
    
    if ($clear_existing) {
        $existing_items = wp_get_nav_menu_items($menu_id);
        if (!empty($existing_items)) {
            foreach ($existing_items as $item) {
                wp_delete_post($item->ID, true);
            }
        }
        $existing_category_ids = [];
    } else {
        $existing_category_ids = acms_get_existing_category_ids_in_menu($menu_id);
    }
    
    // 获取顶级分类
    $top_categories = get_terms([
        'taxonomy'   => 'product_cat',
        'hide_empty' => false,
        'parent'     => 0,
    ]);
    
    if (is_wp_error($top_categories)) {
        return false;
    }
    
    $added_count = 0;
    
    foreach ($top_categories as $category) {
        // 根据层级深度决定是否处理
        $current_depth = 1;
        
        // 如果只需要一级分类
        if ($depth === 1) {
            $added_count += acms_add_single_category_only($category, $menu_id, 0, $existing_category_ids, $clear_existing);
        } 
        // 如果需要更深层级(二级、三级、全部)
        else {
            $added_count += acms_add_category_and_children_to_menu(
                $category,
                $menu_id,
                0,
                $existing_category_ids,
                $clear_existing,
                $depth,
                $current_depth
            );
        }
    }
    
    if ($added_count === 0 && !$clear_existing) {
        return 'nothing_to_sync';
    }
    
    return true;
}

/**
 * 只添加单个分类(不添加子分类)
 * 用于"仅一级分类"模式
 */
function acms_add_single_category_only($category, $menu_id, $parent_menu_item_id = 0, &$existing_category_ids = [], $force_add = false) {
    $added_count = 0;
    
    $already_exists = in_array((int) $category->term_id, $existing_category_ids);
    
    if (!$already_exists || $force_add) {
        if (!($already_exists && !$force_add)) {
            $menu_item_data = [
                'menu-item-object-id'   => $category->term_id,
                'menu-item-object'      => 'product_cat',
                'menu-item-parent-id'   => $parent_menu_item_id,
                'menu-item-type'        => 'taxonomy',
                'menu-item-title'       => $category->name,
                'menu-item-url'         => get_term_link($category),
                'menu-item-status'      => 'publish',
            ];
            
            $menu_item_id = wp_update_nav_menu_item($menu_id, 0, $menu_item_data);
            
            if (!is_wp_error($menu_item_id)) {
                $added_count++;
                $existing_category_ids[] = (int) $category->term_id;
            }
        }
    }
    
    return $added_count;
}

/**
 * 递归添加分类及其子分类(支持层级限制)
 *
 * @param WP_Term $category 分类对象
 * @param int $menu_id 目标菜单ID
 * @param int $parent_menu_item_id 父级菜单项ID
 * @param array &$existing_category_ids 已存在的分类ID列表
 * @param bool $force_add 是否强制添加
 * @param int $max_depth 最大深度:0=无限制, 1=仅当前层, 2=到二级, 3=到三级
 * @param int $current_depth 当前深度(1=一级, 2=二级, 3=三级)
 * @return int 实际新增的菜单项数量
 */
function acms_add_category_and_children_to_menu($category, $menu_id, $parent_menu_item_id = 0, &$existing_category_ids = [], $force_add = false, $max_depth = 0, $current_depth = 1) {
    $added_count = 0;
    $current_menu_item_id = 0;
    
    $already_exists = in_array((int) $category->term_id, $existing_category_ids);
    
    // 判断当前层级是否应该被添加
    $should_add_this_level = true;
    if ($max_depth > 0) {
        // 如果指定了层级限制,只添加匹配层级的分类
        // 例如:max_depth=2 时,只添加当前深度为 2 的分类(不添加深度1和深度3)
        // 但为了保持菜单结构的语义,我们允许添加指定深度的分类,并正确设置其父级
        $should_add_this_level = ($current_depth == $max_depth);
    }
    
    // 如果需要添加当前分类
    if (($should_add_this_level || $max_depth == 0) && (!$already_exists || $force_add)) {
        if (!($already_exists && !$force_add)) {
            $menu_item_data = [
                'menu-item-object-id'   => $category->term_id,
                'menu-item-object'      => 'product_cat',
                'menu-item-parent-id'   => $parent_menu_item_id,
                'menu-item-type'        => 'taxonomy',
                'menu-item-title'       => $category->name,
                'menu-item-url'         => get_term_link($category),
                'menu-item-status'      => 'publish',
            ];
            
            $menu_item_id = wp_update_nav_menu_item($menu_id, 0, $menu_item_data);
            
            if (!is_wp_error($menu_item_id)) {
                $current_menu_item_id = $menu_item_id;
                $added_count++;
                $existing_category_ids[] = (int) $category->term_id;
            }
        } else {
            $current_menu_item_id = acms_get_menu_item_id_by_category($menu_id, $category->term_id);
        }
    } else {
        // 即使不添加当前分类,也需要获取其菜单项ID(如果已存在),用于子分类的父级挂载
        $current_menu_item_id = acms_get_menu_item_id_by_category($menu_id, $category->term_id);
    }
    
    // 处理子分类(如果有)
    // 当 max_depth > 0 且 current_depth >= max_depth 时,不再深入处理子分类
    $should_process_children = ($max_depth == 0) || ($current_depth < $max_depth);
    
    if ($should_process_children && $current_menu_item_id) {
        $children = get_terms([
            'taxonomy'   => 'product_cat',
            'hide_empty' => false,
            'parent'     => $category->term_id,
        ]);
        
        if (!is_wp_error($children) && !empty($children)) {
            $next_depth = $current_depth + 1;
            foreach ($children as $child) {
                $added_count += acms_add_category_and_children_to_menu(
                    $child,
                    $menu_id,
                    $current_menu_item_id,
                    $existing_category_ids,
                    $force_add,
                    $max_depth,
                    $next_depth
                );
            }
        }
    }
    
    return $added_count;
}

/**
 * 根据分类ID获取其在菜单中对应的菜单项ID
 */
function acms_get_menu_item_id_by_category($menu_id, $category_id) {
    $menu_items = wp_get_nav_menu_items($menu_id);
    
    if (!empty($menu_items)) {
        foreach ($menu_items as $item) {
            if ($item->type === 'taxonomy' && 
                $item->object === 'product_cat' && 
                (int) $item->object_id === (int) $category_id) {
                return $item->ID;
            }
        }
    }
    
    return false;
}

给TA打赏
共{{data.count}}人
人已打赏
WordPress插件资源分享

Media Cleaner Pro 7.1.1

2026-6-5 17:35:26

WordPress插件资源分享

Elementor Pro 4.1.0 – WordPress 页面构建器插件 – 模板套件

2026-6-6 18:10:15

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索