递归函数从数据库结果生成多维数组

Dav*_*ill 74 php arrays recursion function

我正在寻找一个函数,它接受一个页面/类别数组(来自平面数据库结果),并根据父ID生成一个嵌套页面/类别项的数组.我想以递归方式执行此操作,以便可以完成任何级别的嵌套.

例如:我在一个查询中获取所有页面,这就是数据库表的样子

+-------+---------------+---------------------------+
|   id  |   parent_id   |           title           |
+-------+---------------+---------------------------+
|   1   |       0       |   Parent Page             |
|   2   |       1       |   Sub Page                |
|   3   |       2       |   Sub Sub Page            |
|   4   |       0       |   Another Parent Page     |
+-------+---------------+---------------------------+
Run Code Online (Sandbox Code Playgroud)

这是我想在我的视图文件中处理的数组:

Array
(
    [0] => Array
        (
            [id] => 1
            [parent_id] => 0
            [title] => Parent Page
            [children] => Array
                        (
                            [0] => Array
                                (
                                    [id] => 2
                                    [parent_id] => 1
                                    [title] => Sub Page
                                    [children] => Array
                                                (
                                                    [0] => Array
                                                        (
                                                            [id] => 3
                                                            [parent_id] => 1
                                                            [title] => Sub Sub Page
                                                        )
                                                )
                                )
                        )
        )
    [1] => Array
        (
            [id] => 4
            [parent_id] => 0
            [title] => Another Parent Page
        )
)
Run Code Online (Sandbox Code Playgroud)

我已经查看并尝试了几乎我遇到过的所有解决方案(Stack Overflow上有很多这样的解决方案,但是没有运气得到足够通用的东西,可以用于页面和类别.

这是我得到的最接近的,但它不起作用,因为我将孩子分配给第一级父母.

function page_walk($array, $parent_id = FALSE)
{   
    $organized_pages = array();

    $children = array();

    foreach($array as $index => $page)
    {
        if ( $page['parent_id'] == 0) // No, just spit it out and you're done
        {
            $organized_pages[$index] = $page;
        }
        else // If it does, 
        {       
            $organized_pages[$parent_id]['children'][$page['id']] = $this->page_walk($page, $parent_id);
        }
    }

    return $organized_pages;
}

function page_list($array)
{       
    $fakepages = array();
    $fakepages[0] = array('id' => 1, 'parent_id' => 0, 'title' => 'Parent Page');
    $fakepages[1] = array('id' => 2, 'parent_id' => 1, 'title' => 'Sub Page');
    $fakepages[2] = array('id' => 3, 'parent_id' => 2, 'title' => 'Sub Sub Page');
    $fakepages[3] = array('id' => 4, 'parent_id' => 3, 'title' => 'Another Parent Page');

    $pages = $this->page_walk($fakepages, 0);

    print_r($pages);
}
Run Code Online (Sandbox Code Playgroud)

dec*_*eze 208

一些非常简单的通用树构建:

function buildTree(array $elements, $parentId = 0) {
    $branch = array();

    foreach ($elements as $element) {
        if ($element['parent_id'] == $parentId) {
            $children = buildTree($elements, $element['id']);
            if ($children) {
                $element['children'] = $children;
            }
            $branch[] = $element;
        }
    }

    return $branch;
}

$tree = buildTree($rows);
Run Code Online (Sandbox Code Playgroud)

算法非常简单:

  1. 获取所有元素的数组和当前父元素的id(最初0/无/ null/无论如何).
  2. 遍历所有元素.
  3. 如果parent_id元素的元素与您在1中得到的当前父ID匹配,则该元素是父元素的子元素.将它放在当前孩子的列表中(这里:) $branch.
  4. 使用您刚刚在3中标识的元素的id递归调用函数,即查找该元素的所有子元素,并将它们添加为children元素.
  5. 返回找到的孩子列表.

换句话说,该函数的一次执行返回一个元素列表,这些元素是给定父ID的子元素.调用它buildTree($myArray, 1),它将返回一个父id为1的元素列表.最初调用父函数为0的函数,因此返回没有父id的元素,它们是根节点.该函数以递归方式调用自身以查找子项的子项.

  • @deceze我也希望看到凌乱的版本.提前致谢! (6认同)

Ale*_*s G 12

我知道这个问题已经过时了,但我遇到了一个非常类似的问题 - 除非有大量的数据.经过一番努力,我设法在结果集的一次传递中构建树 - 使用引用.这段代码并不漂亮,但它的工作原理非常快.它是非递归的 - 也就是说,结果集上只有一个传递,最后一个传递array_filter:

$dbh = new PDO(CONNECT_STRING, USERNAME, PASSWORD);
$dbs = $dbh->query("SELECT n_id, n_parent_id from test_table order by n_parent_id, n_id");
$elems = array();

while(($row = $dbs->fetch(PDO::FETCH_ASSOC)) !== FALSE) {
    $row['children'] = array();
    $vn = "row" . $row['n_id'];
    ${$vn} = $row;
    if(!is_null($row['n_parent_id'])) {
        $vp = "parent" . $row['n_parent_id'];
        if(isset($data[$row['n_parent_id']])) {
            ${$vp} = $data[$row['n_parent_id']];
        }
        else {
            ${$vp} = array('n_id' => $row['n_parent_id'], 'n_parent_id' => null, 'children' => array());
            $data[$row['n_parent_id']] = &${$vp};
        }
        ${$vp}['children'][] = &${$vn};
        $data[$row['n_parent_id']] = ${$vp};
    }
    $data[$row['n_id']] = &${$vn};
}
$dbs->closeCursor();

$result = array_filter($data, function($elem) { return is_null($elem['n_parent_id']); });
print_r($result);
Run Code Online (Sandbox Code Playgroud)

在对此数据执行时:

mysql> select * from test_table;
+------+-------------+
| n_id | n_parent_id |
+------+-------------+
|    1 |        NULL |
|    2 |        NULL |
|    3 |           1 |
|    4 |           1 |
|    5 |           2 |
|    6 |           2 |
|    7 |           5 |
|    8 |           5 |
+------+-------------+
Run Code Online (Sandbox Code Playgroud)

最后一个print_r产生这个输出:

Array
(
    [1] => Array
        (
            [n_id] => 1
            [n_parent_id] => 
            [children] => Array
                (
                    [3] => Array
                        (
                            [n_id] => 3
                            [n_parent_id] => 1
                            [children] => Array
                                (
                                )

                        )

                    [4] => Array
                        (
                            [n_id] => 4
                            [n_parent_id] => 1
                            [children] => Array
                                (
                                )

                        )

                )

        )

    [2] => Array
        (
            [n_id] => 2
            [n_parent_id] => 
            [children] => Array
                (
                    [5] => Array
                        (
                            [n_id] => 5
                            [n_parent_id] => 2
                            [children] => Array
                                (
                                    [7] => Array
                                        (
                                            [n_id] => 7
                                            [n_parent_id] => 5
                                            [children] => Array
                                                (
                                                )

                                        )

                                    [8] => Array
                                        (
                                            [n_id] => 8
                                            [n_parent_id] => 5
                                            [children] => Array
                                                (
                                                )

                                        )

                                )

                        )

                    [6] => Array
                        (
                            [n_id] => 6
                            [n_parent_id] => 2
                            [children] => Array
                                (
                                )

                        )

                )

        )

)
Run Code Online (Sandbox Code Playgroud)

这正是我想要的.