平面数组到多维数组

时间:2012-11-27 10:08:21

标签: php

我在WP中有一个充满导航菜单项的平面阵列。每个项目都知道它的父项,但似乎没有人知道他们是否有孩子。

            Array
(
    [0] => stdClass Object
        (
            [ID] => 22
            [menu_item_parent] => 0
        )
    [1] => stdClass Object
        (
            [ID] => 108
            [menu_item_parent] => 22
        )
    [2] => stdClass Object
        (
            [ID] => 117
            [menu_item_parent] => 108
        )
    [3] => stdClass Object
        (
            [ID] => 118
            [menu_item_parent] => 108
        )
    [4] => stdClass Object
        (
            [ID] => 106
            [menu_item_parent] => 22
        )
    [5] => stdClass Object
        (
            [ID] => 119
            [menu_item_parent] => 106
        )
    [6] => stdClass Object
        (
            [ID] => 120
            [menu_item_parent] => 106
        )
    [7] => stdClass Object
        (
            [ID] => 23
            [menu_item_parent] => 0
        )
)

我尝试用条件逻辑以几种不同的方式接近它(并且每次硬编码值都不理想),但我一直把自己写成一团糟。我如何迭代数组以产生这样的结果?

<ul>
    <li>22
        <ul class="child">
            <li>108
                <ul class="grandchild">
                    <li>117</li>
                    <li>118</li>
                </ul>
            </li>
            <li>106
                <ul class="grandchild">
                    <li>119</li>
                    <li>120</li>
                </ul>
            </li>           
        </ul>
    </li>
    <li>23</li>
</ul>

3 个答案:

答案 0 :(得分:1)

您需要为节点识别子节点,以便将它们放在所需的结构中。为此,您需要迭代元素并重新组织它们。下面是一个粗略的代码,如何做;没有测试过。

$new = array();

foreach ($array as $elm)
{
    if ($elm->menu_item_parent != 0)
    {
        foreach($new as $it)
        {
            $found = false;
            if ($it->ID == $elm->menu_item_parent)
            {
                $it->children[] = $elm;
                $found = true; // Found the parent break loop
            } else if (isset($it->children))
            {
                foreach ($it->children as $child)
                {
                    if ($child->ID == $elm->menu_item_parent)
                    {
                        $child->children[] == $elm;
                        $found = true;
                        break;
                    }
                }

                if ($found) break;
            }
        }
    } else {
        $new[] = $elm; // Parent element - add directly
    }
}

数组$ new现在应该包含具有子节点的元素,您可以迭代它们以产生所需的结果。

这是通过循环当前数组,识别父项及其子节点并按此组织它们来实现的。只会工作两个层次;如果你需要更深入,代码可能需要重新加工以更好地组织它。

答案 1 :(得分:1)

我想首先制作单独的父(主)数组和子数组(或者我们可以使它成为一个长多维数组)

foreach($arr AS $value)
{
    if($value->menu_item_parent == 0)
        $parentArr[] = $value->ID;
    else
        $childArr[$value->menu_item_parent][] = $value->ID; 
}

递归函数将有助于获得一个小的全局解决方案来生成子孙。考虑一下,

$str = '';

echo "<ul>";
foreach($parentArr AS $pValue)
{
    echo '<li>'.$pValue;
        if(in_array($pValue, array_keys($childArr)))
        {
            echo '<ul class="child">';
            $result= childs($pValue); //calling a recursive function (In case one have larger child tree)
            echo $result;
            echo '</ul>';
        }
    echo '</li>';
}
echo '</ul>';

function childs($val)
{
    global $childArr;
    global $str;

    foreach($childArr[$val] AS $cValue)
    {
        $str.= '<li>'.$cValue;

        if(in_array($cValue, array_keys($childArr)))
        {
            $str.= '<ul class="grand_child">';
            childs($cValue);
            $str.= '</ul>';
        }
        $str.= '</li>';
    }

    return $str;
}

必须有一个更好的方法来解决这类问题。

答案 2 :(得分:0)

我最终这样做了:

<?php 
$items = wp_get_nav_menu_items('primary'); // original flat array
foreach ($items as $item) {
    $pages[$item->menu_item_parent][] = $item; // create new array
}
foreach ($pages[0] as $parent) {
    if (isset($pages[$parent->ID])) { // if page has children
        echo '<li>'.$parent->ID;
        echo '<ul class="children">';
        foreach ($pages[$parent->ID] as $child) {
            if (isset($pages[$child->ID])) { // child has children
                echo '<li>'.$child->ID;
                echo '<ul class="grandchildren">';
                foreach ($pages[$child->ID] as $grandchild) {
                    echo '<li>'.$grandchild->ID.'</li>';
                }
                echo '</ul></li>';
            } else {
                echo '<li>'.$child->ID.'</li>'; // child has no children
            }
        }
        echo '</ul></li>';
    } else { // page has no children
        echo '<li>'.$parent->ID.'</li>';
    }
}
?>