По этой теме уже было несколько вопросов, но обычно они касаются превращения иерархических объектов в плоские объекты, что для меня не проблема. Однако в настоящее время я полностью запутался в создании иерархического объекта из плоского объекта.
Предположим, что следующая упрощенная таблица базы данных
id | parent
1 | 0
2 | 1
3 | 1
4 | 3
5 | 4
После запроса к базе данных возвращается следующий объект: $queryResult:
[{id:1, parent:0},
{id:2, parent:1},
{id:3, parent:1},
{id:4, parent:3},
{id:5, parent:4}]
То, что я пытаюсь выполнить с помощью рекурсивного метода, создает объект, идентичный следующему:
[{
id:1,
children:[
{id:2},
{id:3,
children:[
{id:4,
children:[
{id:5}
]
}
]
}
]
}]
У меня есть некоторые начинания, но мой мозг просто не может идти в ногу... Есть ли у кого-нибудь предложения по рекурсивной функции, которая возвращает желаемый объект? Ниже приведен грязный кусок кода (думаю, набросок), который у меня сейчас есть. Он работает правильно, пока функция не будет вызвана рекурсивно, и она не начнет дублировать записи.
function CreateObject($object, $new = array()){
for($i = 0; $i < count($object); $i++){
$found = false;
foreach($object[$i] as $key => $value){
if ($key == 'parent'){
if ($value == 0){
array_push($new, $object[$i]);
} else {
//push into parent
for($j = 0; $j < count($new); $j++){
foreach($new[$j] as $k => $v){
if ($k == 'id' && $v == $value){
$found = true;
if (property_exists($new[$j], 'children')){
array_push($new[$j]->children, $object[$i]);
} else {
$new[$j]->children = array();
array_push($new[$j]->children, $object[$i]);
}
}
}
if (!$found){
foreach($new[$j] as $k => $v){
if ($k == 'children'){
CreateObject($object, $v);
}
}
break;
}
}
}
}
}
}
return $new;
}
$hierarchalObject = CreateObject($flatObject);
С быстро созданным объектом: (это приводит к точно такому же объекту, возвращаемому запросом)
$flatObject = array(
array('id' => 1, 'parent' => 0),
array('id' => 2, 'parent' => 1),
array('id' => 5, 'parent' => 2),
array('id' => 6, 'parent' => 2),
);
$flatObject = json_decode(json_encode($flatObject));
возвращает:
[
{
"id": 1,
"parent": 0,
"children": [
{
"id": 2,
"parent": 1,
"children": [
{
"id": 5,
"parent": 2
},
{
"id": 6,
"parent": 2
},
{ //DUPLICATES HERE
"id": 5,
"parent": 2
},
{
"id": 6,
"parent": 2
}
]
}
]
}
]
Я старался быть максимально полным. Любая помощь будет принята с благодарностью для моего больного мозга.
ОБНОВЛЕНИЕ
Благодаря ответу C3iG3 следующая функция отлично работает в моей ситуации. Это слегка измененная версия ответа C3iG3, включающая все свойства узла, а также не включающая дочернее свойство, если оно пустое.
<?php
function unflatten ( $data )
{
/* Create new node objects */
function create_new_node ( $o ) {
return new class ( $o ) {
public $id;
public function __construct ( $o ) {
//get all properties and assign to node
foreach($o as $key => $value){
if ($key != 'parent'){
$this->$key = $value;
}
}
}
};
}
$roots = array(); // store root nodes
$nodes = array(); // store all nodes
foreach ( $data as $o )
{
$node = isset( $nodes[$o->id] ) ? $nodes[$o->id] : null; // check if node was already created
if ( !$node ) {
$node = create_new_node($o);
}
$nodes[$o->id] = $node; // keep track of node
if ( $o->parent ) // node has a parent
{
if ( !isset( $nodes[$o->parent] ) ) { // if parent node was not already created
$nodes[$o->parent] = create_new_node( $o->parent );
}
$nodes[$o->parent]->children[] = $node; // add node to parent
} else {
$roots[] = $node;
}
}
return $roots;
}
?>
array_push
, я думаю, вы можете просто установить значение, например$new[$j]->children[$k] = $object[$i];
- person WOUNDEDStevenJones   schedule 18.12.2020