I have this array:
$arr = [
["id"=>20,
"name"=>"a",
"parent"=>28,
],
["id"=>21,
"name"=>"a-child",
"parent"=>20,
],
["id"=>27,
"name"=>"a-child-b",
"parent"=>20,
],
["id"=>28,
"name"=>"A parent",
"parent"=>0,
],
["id"=>12,
"name"=>"no parent",
"parent"=>0,
]];
What I want is to group it based on parent
key, where parent = id && parent > 0
or the id
is the parent for this element and the element has parent, if the parent key is greater than zero.
In the above array id=12
has no parent, id=20
has child 21, 27
and it is a child for id=28
.
What I did :
public function sort($arr){
$result = [];
// Get child
foreach($arr as $key => $row) {
if($row['parent'] > 0) {
$result[$row->parent][] = ['id' => $row['id'], 'name' => $row['name']];
unset($arr[$key]);
}
}
// Get parent and append child
foreach($arr as $key => $row) {
$result[$row['id']] = ['name' => $row['name'],
'child' => $result[$row['id']]];
}
return $result;
}
That problem is that, this is only for 1 level of child like parent => child array()
.
What I want to make is a method which gets an argument (above array), where I don't know, how many levels of nesting I will have and returns grouped by parent
key array:
$arr = [
["id"=>28,
"name"=>"A parent",
"parent"=>0,
'child' => [
["id"=>20,
"name"=>"a",
"parent"=>28,
'child' => [
["id"=>21,
"name"=>"a-child",
"parent"=>20,
],
["id"=>27,
"name"=>"a-child-b",
"parent"=>20,
]
]
]
]
],
["id"=>12,
"name"=>"no parent",
"parent"=>0,
]];
A multidimensional array is an array containing one or more arrays. PHP supports multidimensional arrays that are two, three, four, five, or more levels deep. However, arrays more than three levels deep are hard to manage for most people.
flat() is a new array instance method that can create a one-dimensional array from a multidimensional array. By default it only “flats” up to one level. You can add a parameter to flat() to set the number of levels you want to flat the array to.
PHP: array_keys() function The array_keys() function is used to get all the keys or a subset of the keys of an array. Note: If the optional search_key_value is specified, then only the keys for that value are returned. Otherwise, all the keys from the array are returned.
PHP allows a very simple way to declare a multidimensional array in PHP using the keyword 'array'. In order to declare an array inside another array, We need to add the keyword 'array' and then the elements of that array.
<?php
define('ROOT_PARENT',0);
function getHierarchy($records){
$hierarchy = [];
/*
let's assume everybody is going to be a parent
*/
foreach($records as $each_record){
$each_record['child'] = [];
$hierarchy[$each_record['id']] = $each_record;
}
/*
Now add child to parent's key in $hierarchy in the 'child' key.
The & is important since there may be future childs for current child. So pass by reference is needed
*/
foreach($records as $each_record){
$hierarchy[$each_record['parent']]['child'][] = &$hierarchy[$each_record['id']];
}
/*
here I unset every key which wasn't at root level,i.e is 0(top) level
*/
foreach($hierarchy as $parent => $its_data){
if($parent != ROOT_PARENT){
unset($hierarchy[$parent]);
}
}
return isset($hierarchy[ROOT_PARENT],$hierarchy[ROOT_PARENT]['child']) ? $hierarchy[ROOT_PARENT]['child'] : [];
}
$records = [
[
"id" => 20,
"name" => "a",
"parent" => 28,
],
[
"id" => 21,
"name" => "a-child",
"parent" => 20,
],
[
"id" => 27,
"name" => "a-child-b",
"parent" => 20,
],
[
"id" => 28,
"name" => "A parent",
"parent" => 0,
],
[
"id" => 12,
"name" => "no parent",
"parent" => 0,
]
];
echo "<pre>";
print_r(getHierarchy($records));
Output:
Array
(
[0] => Array
(
[id] => 28
[name] => A parent
[parent] => 0
[child] => Array
(
[0] => Array
(
[id] => 20
[name] => a
[parent] => 28
[child] => Array
(
[0] => Array
(
[id] => 21
[name] => a-child
[parent] => 20
[child] => Array
(
)
)
[1] => Array
(
[id] => 27
[name] => a-child-b
[parent] => 20
[child] => Array
(
)
)
)
)
)
)
[1] => Array
(
[id] => 12
[name] => no parent
[parent] => 0
[child] => Array
(
)
)
)
At first, we consider everybody could be a parent. Then, in it's parent's child
key, we keep adding it's children. We pass the key
by reference since there may be future children. Finally, unset()
everybody from the hierarchy that is not a root parent. In the end, you have your final hierarchy structure.
Here's a two-step approach that first builds an associative array mapping parents to arrays of their children, then recursively populates children
keys by indexing into the parent-child associative array.
Note that I assume parent => 0
to be the root but this is also adjustable. I also used the key children
, which I feel is more semantic, but feel free to revert to child
.
function insert(&$curr, $parents) {
if (array_key_exists($curr['id'], $parents)) {
$curr['children'] = $parents[$curr['id']];
}
if (array_key_exists('children', $curr)) {
foreach ($curr['children'] as &$child) {
insert($child, $parents);
}
}
}
function treeify($arr) {
foreach ($arr as $e) {
$parents[$e['parent']][] = $e;
}
foreach ($parents[0] as &$root) {
insert($root, $parents);
}
return $parents[0];
}
Output:
Array
(
[0] => Array
(
[id] => 28
[name] => A parent
[parent] => 0
[children] => Array
(
[0] => Array
(
[id] => 20
[name] => a
[parent] => 28
[children] => Array
(
[0] => Array
(
[id] => 21
[name] => a-child
[parent] => 20
)
[1] => Array
(
[id] => 27
[name] => a-child-b
[parent] => 20
)
)
)
)
)
[1] => Array
(
[id] => 12
[name] => no parent
[parent] => 0
)
)
Try it!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With