PHP hierarchical array - Parents and childs

great answer from @Jens Törnell, just wanted to add a little improvement that if your parent_id and id is actually string instead of number then above method will fail and after creating children array, it will create those childrens arrays again as separate individual array. In order to fix that you should do triple equal check and by telling data type of variable i.e (string) in comparison.

For string based Id and Parent_id in array

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

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

    return $branch;
}

additionally if someone desire, he can add a third parameter to function as well to specify data type of variables dynamically i.e function buildTree(array $elements, $parentId = 0, $datatype='string') but then you will have to take of any other error occur.

hope it will help someone!


The suggestion by @deceze worked. However the input array needs to change a litte, like this...

$rows = array(
    array(
        'id' => 33,
        'parent_id' => 0,
    ),
    array(
        'id' => 34,
        'parent_id' => 0,
    ),
    array(
        'id' => 27,
        'parent_id' => 33,
    ),
    array(
        'id' => 17,
        'parent_id' => 27,
    ),
);

From https://stackoverflow.com/a/8587437/476:

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

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

    return $branch;
}

$tree = buildTree($rows);

print_r( $tree );

I added to @Jens Törnell's answers to enable defining the options for the column name of parent_id, the children array key name, and also the column name for id.

/**
 * function buildTree
 * @param array $elements
 * @param array $options['parent_id_column_name', 'children_key_name', 'id_column_name'] 
 * @param int $parentId
 * @return array
 */
function buildTree(array $elements, $options = [
    'parent_id_column_name' => 'parent_id',
    'children_key_name' => 'children',
    'id_column_name' => 'id'], $parentId = 0)
    {
    $branch = array();
    foreach ($elements as $element) {
        if ($element[$options['parent_id_column_name']] == $parentId) {
            $children = buildTree($elements, $options, $element[$options['id_column_name']]);
            if ($children) {
                $element[$options['children_key_name']] = $children;
            }
            $branch[] = $element;
        }
    }
    return $branch;
}

Since the functionality is quite universal, I managed to use the above function in most of my projects.