PHP: Как заполнить структуру каталогов в массиве - PullRequest
4 голосов
/ 12 декабря 2011

Я разрабатываю панель администратора, которая показывает структуру каталогов определенного местоположения на сервере. У меня есть рекурсивная функция php, которая перебирает все имеющиеся файлы и папки. То, что я не могу понять, как я могу сохранить эту структуру каталогов в ассоциативном массиве php, как это:

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.

Правило, которому я пытаюсь следовать: папка всегда должна быть ключом, а файл всегда должен иметь индекс, подобный следующему:

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

Функция для заполнения этого ассоциативного массива должна быть универсальной, поскольку мы никогда не знаем, какой может быть структура каталогов. Я хочу json_encode этот массив обратно к моему клиенту и иметь дело с ним в JavaScript, который не является проблемой в данный момент.

Если это плохой подход, пожалуйста, дайте мне знать, может быть, есть лучший способ сделать это. Я думал об использовании плоского массива, но я думаю, что это плохой дизайн.

Ответы [ 4 ]

7 голосов
/ 13 декабря 2011
$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);
2 голосов
/ 12 декабря 2011

Вы можете попробовать это, где $ dir - это указанный путь:

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;
}
2 голосов
/ 12 декабря 2011

Этот класс для рекурсивного захвата файлов и каталогов (= включая подкаталоги) путем помещения путей в один пригодный для использования массив даст вам хороший старт:

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

Далее приведу пример того, какиспользовать класс.В вашем случае вам придется пройтись по данным, использовать "explode ('/')" в цикле и создать новый массив, как описано выше.

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

Все, что вам нужно сделатьэто занятьсяВы почти закончили, когда вы берете это отсюда.;)

1 голос
/ 07 августа 2015

Я сделал суть класса дерева сборки.Он использует RecursiveDirectoryIterator и создает массив или JSON для целей ajax.

Вот оно: https://gist.github.com/jonataswalker/3c0c6b26eabb2e36bc90

...