You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:制作适配Bootstrap 4手风琴的WordPress垂直侧边栏Walker类

解决WordPress自定义Walker_Nav_Menu实现Bootstrap 4垂直手风琴侧边栏菜单的问题

我明白你想要实现的Bootstrap手风琴侧边栏菜单结构,你的现有代码主要问题在于没有动态生成手风琴所需的关联ID和ARIA属性,还有一些语法错误和类名不匹配的问题。下面我会帮你重构这个Walker类,完全匹配你需要的HTML结构:

修正后的完整Walker类代码

<?php
class Walker_Indice extends Walker_Nav_Menu {
    // 存储当前折叠菜单的ID,用于关联父链接和子菜单
    private $current_collapse_id;

    public function start_lvl( &$output, $depth = 0, $args = array() ) {
        $indent = str_repeat("\t", $depth);
        // 手风琴父容器的ID(要和wp_nav_menu设置的container_id对应)
        $parent_container_id = '#sidebarIndice';
        // 关联的heading ID(从collapse ID反向生成)
        $aria_labelledby = str_replace('indicecollapse-', 'indiceheading-', $this->current_collapse_id);
        // 判断是否需要默认展开:如果当前项或父项是活跃状态,添加show类
        $show_class = (in_array('current-menu-item', $args->current_item_classes) || in_array('current-menu-ancestor', $args->current_item_classes)) ? ' show' : '';

        // 生成正确的子菜单ul标签
        $output .= "\n$indent<ul id=\"" . esc_attr($this->current_collapse_id) . "\" class=\"collapse$show_class\" aria-labelledby=\"" . esc_attr($aria_labelledby) . "\" data-parent=\"" . esc_attr($parent_container_id) . "\">\n";
    }

    public function end_lvl( &$output, $depth = 0, $args = array() ) {
        $indent = str_repeat("\t", $depth);
        $output .= "$indent</ul>\n";
    }

    public function start_el(&$output, $item, $depth=0, $args=array(), $id=0){
        $indent = ($depth) ? str_repeat("\t", $depth) : '';
        $li_attributes = '';
        $class_names = $value = '';

        // 处理菜单项的class
        $classes = empty( $item->classes ) ? array() : (array) $item->classes;
        $classes[] = ($item->current || $item->current_item_ancestor) ? 'active' : '';
        $classes[] = 'menu-item-' . $item->ID;
        $class_names = join(' ', apply_filters('nav_menu_css_class', array_filter( $classes ), $item, $args));
        $class_names = ' class="' . esc_attr($class_names) . '"';

        // 处理菜单项的ID
        $id = apply_filters('nav_menu_item_id', 'menu-item-' . $item->ID, $item, $args);
        $id = strlen( $id ) ? ' id="' . esc_attr( $id ) . '"' : '';

        // 开始生成li标签
        $output .= $indent . '<li' . $id . $value . $class_names . $li_attributes . '>';

        // 处理链接的属性
        $attributes = ! empty( $item->attr_title ) ? ' title="' . esc_attr($item->attr_title) . '"' : '';
        $attributes .= ! empty( $item->target ) ? ' target="' . esc_attr($item->target) . '"' : '';
        $attributes .= ! empty( $item->xfn ) ? ' rel="' . esc_attr($item->xfn) . '"' : '';
        $attributes .= ! empty( $item->url ) ? ' href="' . esc_attr($item->url) . '"' : '';

        // 如果当前菜单项有子菜单,生成手风琴所需的特殊属性
        if($args->walker->has_children) {
            // 生成唯一的ID对:heading和collapse
            $heading_id = 'indiceheading-' . $item->ID;
            $this->current_collapse_id = 'indicecollapse-' . $item->ID;

            // 判断是否展开:活跃状态则展开,否则折叠
            $is_expanded = (in_array('current-menu-item', $classes) || in_array('current-menu-ancestor', $classes)) ? 'true' : 'false';
            $collapsed_class = ($is_expanded === 'false') ? ' collapsed' : '';

            // 添加手风琴相关属性
            $attributes .= ' id="' . esc_attr($heading_id) . '"';
            $attributes .= ' data-toggle="collapse"';
            $attributes .= ' data-target="#' . esc_attr($this->current_collapse_id) . '"';
            $attributes .= ' aria-expanded="' . esc_attr($is_expanded) . '"';
            $attributes .= ' aria-controls="' . esc_attr($this->current_collapse_id) . '"';
            $attributes .= ' class="custom-class' . $collapsed_class . '"';
        } else {
            // 没有子菜单的普通链接,用你需要的类(如果需要自定义可以修改)
            $attributes .= ' class="custom-class"';
        }

        // 生成链接的内容
        $item_output = $args->before;
        $item_output .= '<a' . $attributes . '>';
        $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
        $item_output .= '</a>'; // 修复原代码漏掉的闭合标签
        $item_output .= $args->after;

        $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
    }
}

关键修改说明

  1. 添加类属性$current_collapse_id:用于在处理子菜单时,关联父链接生成的唯一ID,保证手风琴的点击关联正确。
  2. 动态生成唯一ID对:每个有子菜单的父项都会生成indiceheading-{菜单项ID}和indicecollapse-{菜单项ID}的ID,避免冲突。
  3. 处理ARIA属性和折叠状态:根据菜单项是否为当前活跃项(或父项活跃),自动设置aria-expanded和collapsed类,默认展开活跃菜单。
  4. 修正start_lvl的语法错误:之前的代码错误地写了ul=\"collapse deph_$depth\",现在生成符合Bootstrap要求的折叠菜单容器,包含data-parent关联手风琴父容器。
  5. 修复链接闭合问题:原代码漏掉了</a>闭合标签,这会导致HTML结构混乱,现已补上。

如何调用这个Walker

在你的主题模板(比如sidebar.php)中,用以下代码调用菜单:

wp_nav_menu(array(
    'theme_location' => 'your-sidebar-menu-slug', // 替换成你在后台设置的菜单位置
    'walker' => new Walker_Indice(),
    'container' => 'div',
    'container_id' => 'accordion', // 对应你要的外层div#accordion
    'menu_id' => 'sidebarIndice', // 对应子菜单的data-parent="#sidebarIndice"
    'menu_class' => '', // 去掉默认的menu类,保持你需要的结构
));

额外提示

如果你需要手动强制某个菜单默认展开,不需要依赖活跃状态,可以在WordPress后台的菜单编辑页面,给父菜单项添加自定义classforce-expand,然后在start_el方法中修改$is_expanded的判断逻辑:

$is_expanded = (in_array('force-expand', $classes) || in_array('current-menu-item', $classes) || in_array('current-menu-ancestor', $classes)) ? 'true' : 'false';

内容的提问来源于stack exchange,提问作者ilfedevisio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 22:32:52