0

I have this method that will take a single dimension array and transform it into a multi-dimensional array. It's an adjacency list of categories. I'm injecting an enumerated path as I go. It works 90% of the time.

public function fnExpandArray($aData){

    $aNested = array();

    foreach($aData as &$aCat){

        if(isset($aData[$aCat['parent_id']])){

            $aData[$aCat['parent_id']]['sub'][$aCat['id']] = &$aCat;
            $aData[$aCat['parent_id']]['sub'][$aCat['id']]['path'] = $aData[$aCat['parent_id']]['path'] . '_' . $aCat['id'];

        } else {

            $aNested[$aCat['id']] = &$aCat;
            $aNested[$aCat['id']]['path'] = $aCat['id'];

        }

    }

    unset($aCat);
    return $aNested;
}

This works OK 90% of the time, however the "path" index that is being injected is sometimes being injected after the "sub" index and causing the enumerated path to be calculated incorrectly. Example:

Correct:

 [18] => Array
                    (
                        [id] => 18
                        [parent_id] => 1
                        [title] => Category 1
                        [path] => 1_18
                        [sub] => Array
                            (
                                [150] => Array
                                    (
                                        [id] => 150
                                        [parent_id] => 18
                                        [title] => Category 2
                                        [path] => 1_18_150

But in some iterations it'll inject 'path' after 'sub' and the routine will fail.

Fail:

  [45] => Array
                    (
                        [id] => 45
                        [parent_id] => 2
                        [sub] => Array
                            (
                                [10] => Array
                                    (
                                        [id] => 10
                                        [parent_id] => 45
                                        [sub] => Array
                                            (
                                                [152] => Array
                                                    (
                                                        [id] => 152
                                                        [parent_id] => 10
                                                        [title] => Category 1
                                                        [path] => _152
                                                    )

                                                [79] => Array
                                                    (
                                                        [id] => 79
                                                        [parent_id] => 10
                                                        [title] => Category 2
                                                        [path] => _10_79
                                                    )


                                            )

                                        [title] => Dryers
                                        [path] => _10

Note how path and title are injected after the sub injection. Any idea why?

supert3d
  • 55
  • 7

1 Answers1

0

This method rewrite resolved my issue. Made multiple passes on the array.

public function fnExpandTaxonomy(&$aData) {

    $aTree = array();

    // Loop original flat array, build associative and inject additional indices as required. 
    foreach($aData as $iKey => &$aCat){
        $aTree[$aCat['id']] = &$aCat;
        $aTree[$aCat['id']]['level'] = 0; 
        $aTree[$aCat['id']]['path'] = $aCat['id']; 
        $aTree[$aCat['id']]['sub'] = array(); 
    }

    // Loop - Add children to parents. 
    foreach($aTree as $iKey => &$aCat) {
        if(!$aCat['parent_id']) continue;

        unset($aCat['level'],$aCat['path'],$aCat['sub']);
        $aCat['level'] = $aTree[$aCat['parent_id']]['level']+1; 
        $aCat['path'] = $aTree[$aCat['parent_id']]['path'].'_'.$aCat['id']; 
        $aTree[$aCat['parent_id']]['sub'][$aCat['id']] = &$aCat;

    }

    // Loop again, remove any items that don't have a parent of 0;
    foreach($aTree as $iKey => &$aCat) {
      if(!$aCat['parent_id']) continue;
      unset($aTree[$iKey]);
    }

    unset($aCat);
    return $aTree;  

}   

Big thank you to pyson, whose answer (below) in another similar thread helped me out.

create array tree from array list

Community
  • 1
  • 1
supert3d
  • 55
  • 7