4

I am developing an admin panel that shows the directory structure of a specific location on server. I have got a recursive php function that iterates through every file and folder there is. What I can't figure out is how can I store this directory structure in a php associative array like this:

array[foldername1][0]=file; // if the foldername1 contains a file
array[foldername1][foldername2][0]=file //if foldername1 contains another folder(foldername2) along with the file.

The rule i am trying to follow is; a folder should always be a key and file should always be at an index like this:

array[folder1][folder2][0]=file1;
array[folder1][folder2][1]=file2;

The function to populate this associative array should be generic as we never know what the directory structure can be. I want to json_encode this array back to my client and deal with it in javascript which is not a problem at the moment.

If this is a bad approach please let me know cauze there might be a better way to do this. I thought of using a flat array but i guess its a bad design.

2
  • sorry no idea wat that is...gona look up nw. Thanks Commented Dec 12, 2011 at 19:20
  • 1
    nz.php.net/manual/en/function.glob.php Commented Dec 12, 2011 at 19:21

4 Answers 4

8
$ritit = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(__DIR__), RecursiveIteratorIterator::CHILD_FIRST);
$r = array();
foreach ($ritit as $splFileInfo) {
   $path = $splFileInfo->isDir()
         ? array($splFileInfo->getFilename() => array())
         : array($splFileInfo->getFilename());

   for ($depth = $ritit->getDepth() - 1; $depth >= 0; $depth--) {
       $path = array($ritit->getSubIterator($depth)->current()->getFilename() => $path);
   }
   $r = array_merge_recursive($r, $path);
}

print_r($r);
Sign up to request clarification or add additional context in comments.

4 Comments

hi...chris. i hav got a problem using ur solution!! if the directory is empty...the $r array is empty...no matter how many folders are there. if there are like 5 folders with only one file in them..then i can see the directory struct in my array...is there a way to change it so that if there are only folders and no files; it still gets populated.Thanks.
You deserve a robe and wizard hat. Thanks oodles for this code snipped. Worked out of the box! 10,000 points for you!
Works brilliantly. Any chance of some comments, and an explanation of what's going on? Thanks.
does not work with folders having numbers only. create 2013 and 2014 as folders, now it gives you 2014 and 2015. what?? looks like array_merge_recursive is doing some crazy math here.
2

This class to grab files and directories recursive (= incl. subdirs) by putting the paths in a single, usable array will give you a good headstart:

  class myRecursiveDirectoryParser
  {
     protected $currentPath;
     protected $slash;
     protected $rootPath;
     protected $recursiveTree;

     function __construct($rootPath,$win=false)
     {
        switch($win)
        {
           case true:
              $this->slash = '\\';
              break;
           default:
              $this->slash = '/';
        }
        $this->rootPath = $rootPath;
        $this->currentPath = $rootPath;
        $this->recursiveTree = array(dir($this->rootPath));
        $this->rewind();
     }

     function __destruct()
     {
        $this->close();
     }

     public function close()
     {
        while(true === ($d = array_pop($this->recursiveTree)))
        {
           $d->close();
        }
     }

     public function closeChildren()
     {
        while(count($this->recursiveTree)>1 && false !== ($d = array_pop($this->recursiveTree)))
        {
           $d->close();
           return true;
        }
        return false;
     }

     public function getRootPath()
     {
        if(isset($this->rootPath))
        {
           return $this->rootPath;
        }
        return false;
     }

     public function getCurrentPath()
     {
        if(isset($this->currentPath))
        {
           return $this->currentPath;
        }
        return false;
     }

     public function read()
     {
        while(count($this->recursiveTree)>0)
        {
           $d = end($this->recursiveTree);
           if((false !== ($entry = $d->read())))
           {
              if($entry!='.' && $entry!='..')
              {
                 $path = $d->path.$entry;

                 if(is_file($path))
                 {
                    return $path;
                 }
                 elseif(is_dir($path.$this->slash))
                 {
                    $this->currentPath = $path.$this->slash;
                    if($child = @dir($path.$this->slash))
                    {
                       $this->recursiveTree[] = $child;
                    }
                 }
              }
           }
           else
           {
              array_pop($this->recursiveTree)->close();
           }
        }
        return false;
     }

     public function rewind()
     {
        $this->closeChildren();
        $this->rewindCurrent();
     }

     public function rewindCurrent()
     {
        return end($this->recursiveTree)->rewind();
     }
  }

Next up comes an example of how to use the class. In your case, you would have to walk the data, use "explode('/')" in the loop and construct a new array as you've described above.

  $d = new myRecursiveDirectoryParser("./",false);
  echo($d->getRootPath() . "<br>");
  while (false !== ($entry = $d->read())) {
     echo($entry."<br>");
  }
  $d->close();

All you need to do is get busy. You're almost done when you take it from here. ;)

Comments

2

You could try this, where $dir is a specified path:

function dir_tree($dir) {
   $path = '';
   $stack[] = $dir;
   while ($stack) {
       $thisdir = array_pop($stack);
       if ($dircont = scandir($thisdir)) {
           $i=0;
           while (isset($dircont[$i])) {
               if ($dircont[$i] !== '.' && $dircont[$i] !== '..') {
                   $current_file = "{$thisdir}/{$dircont[$i]}";
                   if (is_file($current_file)) {
                       $path[] = "{$thisdir}/{$dircont[$i]}";
                   } elseif (is_dir($current_file)) {
                        $path[] = "{$thisdir}/{$dircont[$i]}";
                       $stack[] = $current_file;
                   }
               }
               $i++;
           }
       }
   }
   return $path;
}

Comments

1

I've made a gist of a build tree class. It uses RecursiveDirectoryIterator and produce an array or a JSON for ajax purpose.

Here it is: https://gist.github.com/jonataswalker/3c0c6b26eabb2e36bc90

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.