简体   繁体   English

使用递归基于父子关系生成嵌套树结构或层次结构 - PHP

[英]Generate Nested Tree Structure or Hierarchy based on parent child relationship using recursion - PHP

I've been stuck in this since yesterday any help will be much appreciated.自昨天以来,我一直坚持这一点,任何帮助将不胜感激。 The situation is this: I have a table for navigation links with the following structure, id |情况是这样的:我有一个导航链接表,其结构如下: id | parent_id | parent_id | text文本

In my scenario the parent_id may be null(no sub-menu) or any id pointing back to the table which will make the record a sub-menu of the parent.在我的场景中,parent_id 可能为空(无子菜单)或任何指向表的 id,这将使记录成为父级的子菜单。 I've tried many different ways to execute this but with no luck, the closest scenario I came up with is the following,我尝试了许多不同的方法来执行此操作,但没有运气,我想出的最接近的情况如下,

// All navigation link results are stored in $data
public static function transform(array &$data) {
    $result = [];
    $search = function(&$array = [], $parent = null) use (&$search, &$result){
        foreach($array as $key => $value) {
            /** If the element has an ancestor */
            if($parent && $parent->id == $value->parent_id) {
                $next = $parent->children[] = $value;
                $search($array, $next);
                unset($array[$key]);
            }
        }

        return $parent;
    };

    foreach($data as $val) {
        $result[] = $search($data, $val);
    }
    return $result;
}

The function works fine and tracks all the ancestors of a certain link but in the next iteration is tracking all the ancestors of the next element(even if it was a child of the previous one) so it comes back with a lot of duplicated data.该函数工作正常并跟踪某个链接的所有祖先,但在下一次迭代中跟踪下一个元素的所有祖先(即使它是前一个元素的子元素),因此它会返回大量重复数据。 I came up with the solution to unset the iterated element from the array but for some reason, the element is still being used in the next iteration.我想出了从数组中取消设置迭代元素的解决方案,但由于某种原因,该元素仍在下一次迭代中使用。 Here is my current data这是我目前的数据

Here is my current result这是我目前的结果

A simple concept for faster search and to process one item only once.用于更快搜索和仅处理一个项目一次的简单概念。

  • Create a temp array with key as id and values as array of child ids .创建一个临时数组, key as idvalues as array of child ids Will use this array to process next direct childs.将使用此数组来处理下一个直接子项。 It would be a depth first traversal.这将是深度优先遍历。
  • Also set id as key in input array, so we can directly access whole node when required.还要将id设置为输入数组中的键,这样我们就可以在需要时直接访问整个节点。
function generateTree($data){
    $arrChild = [];   // Store parent as key and its childs as array to quickly find out.
    foreach($data as $obj){
        $arrChild[$obj->parent_id][] = $obj->id;
        $data[$obj->id] = $obj;
    }
    
    $final = [];
    
    $setChild = function(&$array, $parents) use (&$setChild, $data, $arrChild){
        foreach($parents as $parent){
            $temp = $data[$parent];
            // If key is set, that means given node has direct childs, so process them too.
            if(isset($arrChild[$parent])){
                $temp->children = [];
                $setChild($temp->children, $arrChild[$parent]);
            }
            $array[] = $temp;
        }    
    };
    // Empty key would represent nodes with parent as `null`
    $setChild($final, $arrChild['']);
    return $final;
}

$final = generateTree($arr);

echo json_encode($final, JSON_PRETTY_PRINT);

Output:输出:

[
    {
        "id": 1,
        "navigation_id": 4,
        "parent_id": null,
        "text": "link 1",
        "icon": "",
        "url": null,
        "page_id": 4,
        "children": [
            {
                "id": 2,
                "navigation_id": 4,
                "parent_id": 1,
                "text": "link 2",
                "icon": "",
                "url": null,
                "page_id": 4,
                "children": [
                    {
                        "id": 3,
                        "navigation_id": 4,
                        "parent_id": 2,
                        "text": "link 3",
                        "icon": "fas fa-ad",
                        "url": "https:\/\/google.com",
                        "page_id": null
                    },
                    {
                        "id": 4,
                        "navigation_id": 4,
                        "parent_id": 2,
                        "text": "link 4",
                        "icon": "fab fa-google",
                        "url": "https:\/\/google.com",
                        "page_id": null
                    }
                ]
            }
        ]
    },
    {
        "id": 5,
        "navigation_id": 4,
        "parent_id": null,
        "text": "link 5",
        "icon": "",
        "url": null,
        "page_id": 5,
        "children": [
            {
                "id": 6,
                "navigation_id": 4,
                "parent_id": 5,
                "text": "link 6",
                "icon": "",
                "url": null,
                "page_id": 4
            },
            {
                "id": 7,
                "navigation_id": 4,
                "parent_id": 5,
                "text": "link 7",
                "icon": "",
                "url": null,
                "page_id": 4
            }
        ]
    }
]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM