skip to Main Content

I have a table that contains a directory structure. There is an item ID and a DirectoryID. The DirectoryID refers to an item ID and is, as such, a child directory under the parent directory. An example below:

# ID, DirectoryID, DirectoryName
'1', '0', 'Root Dir'
'2', '0', 'Another Root Dir'
'3', '2', 'TESTING456'
'4', '3', 'TESTING789'
'5', '1', 'TESTINGMORE'
'6', '4', 'RANDOM DIR'

Using PHP, how do I build that into an array that looks like the one below?

$array = [
   [2 => 'Another Root Dir',3 => 'TESTING456', 4 => 'TESTING789', 6 => 'RANDOM DIR'],
   [1 => 'Root Dir',5 => 'TESTINGMORE']
];

2

Answers


  1. If you mean list of all paths for directory array, first create tree then we’ll iterate it. I will start with JS because it’s more fun.

    // ID, DirectoryID, DirectoryName
    var arr = [
      ['1', '0', 'Root Dir'],
      ['2', '0', 'Another Root Dir'],
      ['3', '2', 'TESTING456'],
      ['4', '3', 'TESTING789'],
      ['5', '1', 'TESTINGMORE'],
      ['6', '4', 'RANDOM DIR']
    ]
    
    console.log(do_arr(arr));
    
    function do_arr(arr) {
    
      // grouping by id for easy access
      var grouped = arr.reduce(function(agg, [id, parent, name]) {
        agg[id] = { id, parent, name }
        return agg;
      }, {})
    
      // we want 1 root for all others
      grouped['0'] = { id: 0, name: 'really-main-root' }
    
      // creating tree with children
      arr.forEach(function([id, parent, name]) {
        grouped[parent].children = grouped[parent].children || []
        grouped[parent].children.push(id)
      })
    
      // doing all_paths
      var result = [];
      function iterate(obj, so_far) {
        if (obj.children) {
          obj.children.forEach(function(child_id) {
            iterate(grouped[child_id], so_far.concat({
              id: child_id,
              name: grouped[child_id].name
            }));
          })
        } else {
          result.push(so_far)
        }
      }
      iterate(grouped[0], [])
      
      return result;
    }
    .as-console-wrapper {
      max-height: 100% !important
    }

    And here’s the PHP version:

    
    $arr = [
        ['1', '0', 'Root Dir'],
        ['2', '0', 'Another Root Dir'],
        ['3', '2', 'TESTING456'],
        ['4', '3', 'TESTING789'],
        ['5', '1', 'TESTINGMORE'],
        ['6', '4', 'RANDOM DIR'],
    ];
    
    print_r(do_arr($arr));
    
    function do_arr($arr)
    {
    
        // grouping by id for easy access
        $grouped = array_reduce($arr, function ($agg, $item) {
            $id = $item[0];
            $parent = $item[1];
            $name = $item[2];
            $agg[$id] = compact('id', 'parent', 'name');
            return $agg;
        }, []);
    
        // we want 1 root for all others
        $grouped['0'] = ['id' => '0'];
    
        // creating tree with children
        foreach ($grouped as $item) {
            extract($item);
            if (isset($parent)) {
                $grouped[$parent]["children"][] = $id;
            }
        }
    
        // doing all_paths
        $result = [];
        function iterate($obj, $so_far = [], $grouped, &$result)
        {
            if (isset($obj["children"])) {
                foreach ($obj["children"] as $child_id) {
                    if ($child_id) {
                        iterate($grouped[$child_id], array_merge($so_far, [$child_id => $grouped[$child_id]['name']]), $grouped, $result);
                    }
                }
            } else {
                $result[] = $so_far;
            }
        }
        iterate($grouped['0'], [], $grouped, $result);
        return $result;
    }
    
    Login or Signup to reply.
  2. Loop through the root nodes and then for each children.

    $dirs = [
        ['1', '0', 'Root Dir'],
        ['2', '0', 'Another Root Dir'],
        ['3', '2', 'TESTING456'],
        ['4', '3', 'TESTING789'],
        ['5', '1', 'TESTINGMORE'],
        ['6', '4', 'RANDOM DIR'],
    ];
    
    $array = [];
    foreach (array_filter($dirs, fn($dir) => '0' === $dir[1]) as $root) {
        $parent  = $root[0];
        $current = [$parent => $root[2]];
        while ($children = array_filter($dirs, fn($dir) => $dir[1] === $parent)) {
            $child            = reset($children);
            $parent           = $child[0];
            $current[$parent] = $child[2];
        }
        $array[] = $current;
    }
    
    print_r($array);
    

    Output

    Array
    (
        [0] => Array
            (
                [1] => Root Dir
                [5] => TESTINGMORE
            )
    
        [1] => Array
            (
                [2] => Another Root Dir
                [3] => TESTING456
                [4] => TESTING789
                [6] => RANDOM DIR
            )
    
    )
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search