首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >循环时产生重复结果的递归foreach()

循环时产生重复结果的递归foreach()
EN

Stack Overflow用户
提问于 2017-04-15 04:32:54
回答 2查看 127关注 0票数 0

这个类被设计成迭代一个WordPress菜单结构(嵌套数组/对象)来生成一个完整的菜单。虽然我的数据来源是WordPress,但我觉得这个问题属于SO而不是WP.SO,因为这个问题更多地植根于PHP (适用于任何尝试递归的人)。

由于某些原因,我在层次结构中看到了重复的结果。另外,我注意到某些HTML元素没有正确关闭。似乎我已经正确地嵌套了所有的东西,但是结果就是你在这里看到的。

为了帮助调试,我添加了一些*以直观地影响标记。也许你们知道一些我不知道的事情。手指祝福,并提前感谢你的意见!

我的班

代码语言:javascript
运行
复制
class Nav_Menu
{
    public $wp_nav;
    public $nested_nav;
    public $recursion_depth = 0;

    function __construct( $menu, $args = array() )
    {
        $format = new Format;

        if( $menu )
        {
            $this->wp_nav = wp_get_nav_menu_items($menu, $args);
            $this->nested_nav = $this->build_tree($this->wp_nav);

            $output = $this->build_output($this->nested_nav);
            $output_formatted = $format->HTML($output);

            // echo $output;
            echo $output_formatted;
        }
    }

    private function build_output( $menu = array() )
    {
        $output = '**';
        $output.= $this->recurse_menu($menu, $output);

        return $output;
    }

    private function recurse_menu( $menu = array(), $output )
    {
        global $post;

        if( !empty($menu) && !empty($output) )
        {
            $this->recursion_depth++;

            // ul classes
            $classes_ul = array();
            $classes_ul[] = ( $this->recursion_depth > 1 ? 'sub-menu' : '' );
            $classes_ul[] = 'depth-' . $this->recursion_depth;

            // process list wrappers
            $output.= '<ul class="' . $this->process_classes($classes_ul) . '">';

            // loop through menu items
            foreach( $menu as $menu_key => $menu_val )
            {
                // process list items
                $output.= '<li>' . $menu_val->title;

                // if necessary, handle children and recurse
                if( !empty($menu_val->children) )
                {
                    // recurse, and call this again
                    $output.= $this->recurse_menu($menu_val->children, $output);
                }

                // process list items
                $output.= '</li>';
            }

            // process list wrappers
            $output.= '</ul>';
        }

        return $output;
    }

    private function process_classes($classes = array())
    {
        if( !$classes )
        {
            return;
        }

        return trim(implode(' ', $classes));
    }

    private function build_tree( $elements = array(), $parent_id = 0 )
    {
        $branch = array();
        foreach($elements as $element)
        {
            if ($element->menu_item_parent == $parent_id)
            {
                $children = $this->build_tree($elements, $element->ID);
                if ($children)
                {
                    $element->children = $children;
                }

                $branch[] = $element;
            }
        }

        return $branch;
    }
}

$mynav = new Nav_Menu('Test Menu');

结果输出

代码语言:javascript
运行
复制
****
<ul class="depth-1">
    <li>
        One**
        <ul class="depth-1">
            <li>
                One
                <ul class="sub-menu depth-2">
                    <li>
                        Sub One
                    </li>
                    <li>
                        Sub Two
                    </li>
                    <li>
                        Sub Three
                    </li>
                </ul>
            </li>
            <li>
                Two
            </li>
            <li>
                Three**
                <ul class="depth-1">
                    <li>
                        One**
                        <ul class="depth-1">
                            <li>
                                One
                                <ul class="sub-menu depth-2">
                                    <li>
                                        Sub One
                                    </li>
                                    <li>
                                        Sub Two
                                    </li>
                                    <li>
                                        Sub Three
                                    </li>
                                </ul>
                            </li>
                            <li>
                                Two
                            </li>
                            <li>
                                Three
                                <ul class="sub-menu depth-3">
                                    <li>
                                        Sub One
                                    </li>
                                    <li>
                                        Sub Two
                                    </li>
                                </ul>
                            </li>
                            <li>
                                Four
                            </li>
                        </ul>

后端WordPress菜单

EN

回答 2

Stack Overflow用户

发布于 2017-04-15 05:15:00

如果有人知道原因,我会愿意知道,所以我会保留选择一个答案暂时。我猜是变量$output的某种奇怪的名称空间/范围问题。谁知道呢我现在有点累了。

找到一个合法结构的办法是.

代码语言:javascript
运行
复制
class Nav_Menu
{
    public $wp_nav;
    public $nested_nav;
    public $recursion_depth = 0;
    public $output = '';

    function __construct( $menu, $args = array() )
    {
        $format = new Format;

        if( $menu )
        {
            $this->wp_nav = wp_get_nav_menu_items($menu, $args);
            $this->nested_nav = $this->build_tree($this->wp_nav);

            $this->build_output($this->nested_nav);
            $output_formatted = $format->HTML($this->output);

            // echo $this->output;
            echo $output_formatted;
        }
    }

    private function build_output( $menu = array() )
    {
        $this->recurse_menu($menu);
    }

    private function recurse_menu( $menu = array() )
    {
        global $post;

        if( !empty($menu) )
        {
            $this->recursion_depth++;

            // ul classes
            $classes_ul = array();
            $classes_ul[] = ( $this->recursion_depth > 1 ? 'sub-menu' : '' );
            $classes_ul[] = 'depth-' . $this->recursion_depth;

            // process list wrappers
            $this->output.= '<ul class="' . $this->process_classes($classes_ul) . '">';

            // loop through menu items
            foreach( $menu as $menu_key => $menu_val )
            {
                // process list items
                $this->output.= '<li>';
                $this->output.= $menu_val->title;

                // if necessary, handle children and recurse
                if( !empty($menu_val->children) )
                {
                    // recurse, and call this again
                    $this->recurse_menu($menu_val->children);
                }

                // process list items
                $this->output.= '</li>';
            }

            // process list wrappers
            $this->output.= '</ul>';
        }
    }

    private function process_classes($classes = array())
    {
        if( !$classes )
        {
            return;
        }

        return trim(implode(' ', $classes));
    }

    private function build_tree( $elements = array(), $parent_id = 0 )
    {
        $branch = array();
        foreach($elements as $element)
        {
            if ($element->menu_item_parent == $parent_id)
            {
                $children = $this->build_tree($elements, $element->ID);
                if ($children)
                {
                    $element->children = $children;
                }

                $branch[] = $element;
            }
        }

        return $branch;
    }
}

$mynav = new Nav_Menu('Test Menu'); exit;

结果输出

代码语言:javascript
运行
复制
<ul class="depth-1">
    <li>
        One
        <ul class="sub-menu depth-2">
            <li>
                Sub One
            </li>
            <li>
                Sub Two
            </li>
            <li>
                Sub Three
            </li>
        </ul>
    </li>
    <li>
        Two
    </li>
    <li>
        Three
        <ul class="sub-menu depth-3">
            <li>
                Sub One
            </li>
            <li>
                Sub Two
            </li>
        </ul>
    </li>
    <li>
        Four
    </li>
</ul>

我只是为类创建了一个私有变量,每次我需要将它作为存储位置引用时,我只需将其附加到其中。和以前一样,但不再需要将$output传递到某个疯狂的方法链中。

如果任何人有任何其他的想法,可以帮助社区,请分享!

票数 0
EN

Stack Overflow用户

发布于 2017-04-15 06:13:51

更新您的build_output方法如下:

代码语言:javascript
运行
复制
private function build_output( $menu = array() )
{
    $output = '<ul>';
    $output = $this->recurse_menu($menu, $output);
    $output.= '</ul>';
    return $output;
}

更新您的recurse_menu方法如下:

代码语言:javascript
运行
复制
private function recurse_menu( $menu = array(), $output = '')
{
     global $post;
     if( !empty($menu))
      {
        $this->recursion_depth++;
        // ul classes
        $classes_ul = array();
        $classes_ul[] = ( $this->recursion_depth > 1 ? 'sub-menu' : '' );
        $classes_ul[] = 'depth-' . $this->recursion_depth;

        // loop through menu items
        foreach( $menu as $menu_key => $menu_val )
        {
            // if necessary, handle children and recurse
            if( !empty($menu_val->children) )
            {
                // recurse, and call this again
                $output.= '<li><a href="#">'.$menu_val->title.'</a><ul class="' . $this->process_classes($classes_ul) . '">'.$this->recurse_menu($menu_val->children).'</ul></li>';

            }
            else {
            $output.= '<li><a href="#">'.$menu_val->title.'</a></li>';
            }

        }
    }

    return $output;
}

注意:我已经用更多的子级别测试了它,而且它运行得很好。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43422222

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档