[英]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这是我目前的数据
A simple concept for faster search and to process one item only once.用于更快搜索和仅处理一个项目一次的简单概念。
key as id
and values as array of child ids
.创建一个临时数组, key as id
, values as array of child ids
。 Will use this array to process next direct childs.将使用此数组来处理下一个直接子项。 It would be a depth first traversal.这将是深度优先遍历。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.