web-dev-qa-db-ja.com

サブメニューのメニューウォーカーで最上位の親を表示

以下のメニューウォーカーを使用して、過去に大きな効果を持つ動的サブメニューを表示しました。

現在のページがそのページの親、兄弟、または子孫である場合は、2番目または下位のメニュー項目が表示されます。

たとえば、メニュー階層が次のようになっているとします。

  • ある
  • b
    • 1
      • ii

ページB、1、i、またはiiの場合は、1、i、およびiiが表示されます。最上位の親も表示されるように、親項目(例ではB)をそれに追加します。

私はこのコードを理解しようと、ウォーカーについて読んだことがありますが、それでもどこから始めても動けなくなります。

// Show only the child pages of a menu
class child_menu_walker extends Walker_Nav_Menu {
    var $found_parents = array();

    function start_el(&$output, $item, $depth, $args) {
        global $wp_query;

        if( $wp_query->is_single && !in_array( get_option('page_for_posts'), $this->found_parents ) ) {
            $this->found_parents[] = get_option('page_for_posts');
        }

        //this only works for second level sub navigations
        $parent_item_id = 0;

        $indent = ($depth) ? str_repeat("\t", $depth) : '';

        $class_names = '';
        $classes = empty($item->classes) ? array() : (array) $item->classes;
        $class_names = join(' ', apply_filters('nav_menu_css_class', array_filter($classes), $item));
        $class_names = ' class="'.esc_attr($class_names).'"';

        #current_page_item
        // Checks if the current element is in the current selection
        if(
            strpos($class_names, 'current-menu-item') || 
            strpos($class_names, 'current-menu-parent') || 
            strpos($class_names, 'current-menu-ancestor') || 
            ( is_array($this->found_parents) && 
                in_array($item->menu_item_parent, $this->found_parents) )
        ) {
            // Keep track of all selected parents
            $this->found_parents[] = $item->ID;
            //check if the item_parent matches the current item_parent
            $item_output = '';
            if ($item->menu_item_parent != $parent_item_id ) {
                $output .= $indent.'<li'.$class_names.'>';

                $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).'"' : '';

                $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);
        }
    }

    function end_el(&$output, $item, $depth) {
        $parent_item_id = 0;

        $class_names = '';
        $classes = empty($item->classes) ? array() : (array) $item->classes;
        $class_names = join(' ', apply_filters('nav_menu_css_class', array_filter($classes), $item));
        $class_names = ' class="'.esc_attr($class_names).'"';

        if(
            strpos($class_names, 'current-menu-item') || 
            strpos($class_names, 'current-menu-parent') || 
            strpos($class_names, 'current-menu-ancestor') || 
            (is_array($this->found_parents) && 
                in_array($item->menu_item_parent, $this->found_parents))
        ) {
            // Closes only the opened li
            if (is_array($this->found_parents) && in_array($item->ID, $this->found_parents) && $item->menu_item_parent != $parent_item_id) {
                $output .= "</li>\n";
            }
        }
    }

    function end_lvl(&$output, $depth) {
        $indent = str_repeat("\t", $depth);
        // If the sub-menu is empty, strip the opening tag, else closes it
        if (substr($output, -22) == "<ul class=\"sub-menu\">\n") {
            $output = substr($output, 0, strlen($output) - 23);
        } else {
            $output .= "$indent</ul>\n";
        }
    }
}
3
mrwweb

child_menu_walkerクラスのstart_el()メソッドで、次のif-条件をスキップすることもできます。

if ($item->menu_item_parent != $parent_item_id ) {
    //...
}

これは以下と同じです。

if ($item->menu_item_parent != 0 ) {
    //...
}

$parent_item_id = 0があるので。

したがって、この条件はあなたの トップレベルの親 を除外しているように見えます。

またこの条件を再考したいと思うかもしれません:

&& $item->menu_item_parent != $parent_item_id

end_el()メソッドで。

1
birgire