0

I'm trying to fill data json for treemaker.js from database data; the result set looks like this:

[
    ['id' => 1, 'root' => 1, 'parent_id' => 0],
    ['id' => 2, 'root' => 1, 'parent_id' => 1],
    ['id' => 3, 'root' => 1, 'parent_id' => 2],
    ['id' => 4, 'root' => 1, 'parent_id' => 2],
    ['id' => 5, 'root' => 1, 'parent_id' => 3],
    ['id' => 6, 'root' => 1, 'parent_id' => 3],
    ['id' => 7, 'root' => 1, 'parent_id' => 4],
    ['id' => 8, 'root' => 1, 'parent_id' => 4],
    ['id' => 9, 'root' => 1, 'parent_id' => 4],
]

I expected the json output should be like this:

{ 
    '1': {
        '2': {
            '3': {
                '5': '',
                '6': '',
            },
            '4': {
                '7': '',
                '8': '',
                '9': '',
            },
        },
    },
}

I already tried :

function buildTree(array $elements, $parentId = 0) {
    $branch = [];
    $new = [];
    foreach ($elements as $element) {
        if ($element['parent_id'] == $parentId) {
            $children = $this->buildTree($elements, $element['id']);
            if ($children) {
                $element[$element['id']] = $children;
            } else {
                $element[$element['id']] = '';
            }
            unset($element["id"]);
            unset($element["root"]);
            unset($element["parent_id"]);
            $branch[] = $element;
        }
    }
    return $branch;
}

public function test($id)
{
    $data = $this->Data_model->getDataByRoot($id)->result_array();
    $tree = $this->buildTree($data);
    echo "<pre>";
    print_r( json_encode($tree, JSON_PRETTY_PRINT|JSON_FORCE_OBJECT));
}

I got the reference from PHP hierarchical array - Parents and childs, but the result is like this.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
smlos
  • 57
  • 1
  • 6

2 Answers2

0

Here is my solution:

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

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

            if ($children) {
                $branch[$id] = $children;
            } else {
                $branch[$id] = '';
            }
        }
    }
    return $branch;
}
Richard Dobroň
  • 687
  • 4
  • 6
0

While iterating and recursing when a matching parent_id is encountered, push the child data into an element which is keyed by the current row's id. If there are no children for the row, fall back to an empty string with the shorthand ternary operator (aka "Elvis operator").

Code: (Demo)

function buildTree(array $rows, int $parentId = 0): array {
    $new = [];
    foreach ($rows as $row) {
        if ($row['parent_id'] == $parentId) {
            $new[$row['id']] = buildTree($rows, $row['id']) ?: '';
        }
    }
    return $new;
}

$resultSet = [
    ['id' => 1, 'parent_id' => 0],
    ['id' => 2, 'parent_id' => 1],
    ['id' => 3, 'parent_id' => 2],
    ['id' => 4, 'parent_id' => 2],
    ['id' => 5, 'parent_id' => 3],
    ['id' => 6, 'parent_id' => 3],
    ['id' => 7, 'parent_id' => 4],
    ['id' => 8, 'parent_id' => 4],
    ['id' => 9, 'parent_id' => 4],
];

var_export(
    buildTree($resultSet)
);

My advice largely resembles the advice given here.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136