Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Traversing Function to turn single array into nested array with children - based on parent id

I have an array similar to this:

Array
(
    Array
    (
        [ID] => 1
        [parentcat_ID] => 0
    ),
    Array
    (
        [ID] => 2
        [parentcat_ID] => 0
    ),
    Array
    (
        [ID] => 6
        [parentcat_ID] => 1
    ),
    Array
    (
        [ID] => 7
        [parentcat_ID] => 1
    ),
    Array
    (
        [ID] => 8
        [parentcat_ID] => 6
    ),
    Array
    (
        [ID] => 9
        [parentcat_ID] => 1
    ),
    Array
    (
        [ID] => 13
        [parentcat_ID] => 7
    ),
    Array
    (
        [ID] => 14
        [parentcat_ID] => 8
    )

)

But I need a function to recursively put each item into a 'children' array inside the relevant parent array. So it would look more like this:

Array
(
    Array
    (
        [ID] => 1
        [parentcat_ID] => 0
        [children] => Array (
            Array
            (
                [ID] => 6
                [parentcat_ID] => 1
                [childen] => Array (
                    Array
                    (
                        [ID] => 8
                        [parentcat_ID] => 6
                        [children] => Array (
                             Array
                             (
                                 [ID] => 14
                                 [parentcat_ID] => 8
                             )
                        )
                    )
                )
            ),
            Array
            (
                [ID] => 7
                [parentcat_ID] => 1
                [children] => Array(
                     Array
                     (
                         [ID] => 13
                         [parentcat_ID] => 7
                     )
                ) 
            ),
            Array
            (
                [ID] => 9
                [parentcat_ID] => 1
            )

        )
    )
    Array
    (
        [ID] => 2
        [parentcat_ID] => 0

    )

)

I hope that makes sense!

like image 250
Joel Avatar asked Dec 06 '22 03:12

Joel


2 Answers

Give this a go (tested under php 5.2):

$inArray = array(
    array('ID' => '1', 'parentcat_ID' => '0'),
    array('ID' => '2', 'parentcat_ID' => '0'),
    array('ID' => '6', 'parentcat_ID' => '1'),  
    array('ID' => '7', 'parentcat_ID' => '1'),
    array('ID' => '8', 'parentcat_ID' => '6'),          
    array('ID' => '9', 'parentcat_ID' => '1'),  
    array('ID' => '13', 'parentcat_ID' => '7'),
    array('ID' => '14', 'parentcat_ID' => '8'),     
);

function makeParentChildRelations(&$inArray, &$outArray, $currentParentId = 0) {
    if(!is_array($inArray)) {
        return;
    }

    if(!is_array($outArray)) {
        return;
    }

    foreach($inArray as $key => $tuple) {
        if($tuple['parentcat_ID'] == $currentParentId) {
            $tuple['children'] = array();
            makeParentChildRelations($inArray, $tuple['children'], $tuple['ID']);
            $outArray[] = $tuple;   
        }
    }
}

$outArray = array();
makeParentChildRelations($inArray, $outArray);

print_r($outArray);
like image 52
Max Avatar answered Dec 07 '22 16:12

Max


I recently answered a similar question. Here it is. Hope it suits your needs. If not, let me know, and I'll adjust it to your specs.

EDIT
Alright, here is the adjusted version that should suit your needs.

function generateMultiArray( array $flatArray )
{

    // initiate result array
    $multiArray = array();

    // iterate $flatArray
    foreach( $flatArray as $item )
    {
        // for convenience, initiate these vars
        $id = $item[ 'ID' ];
        $parentId = $item[ 'parentcat_ID' ];

        // initiate this item's children array;
        $item[ 'children' ] = array();

        // if parent doesn't exist yet, initiate it along with an empty 'children' array
        if( !isset( $multiArray[ $parentId ] ) )
        {
            $multiArray[ $parentId ] = array(
                'children' => array()
            );
        }

        // if this item is initiated already (as being a parent) merge it with the current item
        $multiArray[ $id ] = isset( $multiArray[ $id ] ) ? $multiArray[ $id ] + $item : $item;

        // add this item to the parents children collection by reference (for efficiency)
        $multiArray[ $parentId ][ 'children' ][ $id ] = &$multiArray[ $id ];

    }

    return $multiArray;
}

Mind you that this function also makes all items accessible as a root item of the result array with their ID as the index.

So, to access children of an item with arbitrary id n, you would do:

$multiArray = generateMultiArray( $yourFlatArray );
$children = $multiArray[ n ][ 'children' ]; // replace n with the id

EDIT 2
Forgot to intitiate children array for items that aren't a parent; added now. Otherwise it would result in a notice when trying to access it with:

$multiArray = generateMultiArray( $yourFlatArray );
$children = $multiArray[ $someIdWithoutChildren ][ 'children' ];
like image 27
Decent Dabbler Avatar answered Dec 07 '22 17:12

Decent Dabbler