PHP hierarchical array - Parents and childs

54,338

Solution 1

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 );

Solution 2

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.

Solution 3

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!

Share:
54,338

Related videos on Youtube

Jens Törnell
Author by

Jens Törnell

Updated on April 26, 2020

Comments

  • Jens Törnell
    Jens Törnell about 4 years

    I use PHP and mySQL with Idiorm. That might not be relevant.

    My PHP array

    • It's a relationship between parents and childs.
    • 0 is the root parent.
    • Example: Root parent 0 have the child 33 which have the child 27 which have the child 71.

    This array structure can be changed if needed for solving the problem.

    array (
      33 => 
        array (
          0 => '27',
          1 => '41',
      ),
      27 => 
        array (
          0 => '64',
          1 => '71',
      ),
      0 => 
        array (
          0 => '28',
          1 => '29',
          2 => '33',
      ),
    )
    

    My hierarchical result

    Something like this, but as an array...

      0 => 
          28
          29
          33
             27 =>
                   64
                   71
             41
    

    Information

    • The depth are unkown and it can be unlimited. I tried foreach, but it might not be the way.

    My own thoughts

    • Some recursive function?
    • Some while loops?

    I tried both of the above, just got a mess. It's a brainer.

  • Danish
    Danish over 6 years
    just added a little improvement in my answer, hope that's ok!
  • Ahmad Budairi
    Ahmad Budairi about 5 years
    Not working here. When the data type added then the result i got is empty.But when i the data type removed then the result shown there.
  • Gilly
    Gilly over 4 years
    This is a great solution if you don't want to run multiple queries or left joins or even unions on a table with parent_id structure!
  • funder7
    funder7 over 2 years
    Interesting one. Your problem was that anyone can be the root? I usually consider the root being the one with parentId = null, but probably is not your case.