1

多次元配列でディレクトリ構造を取得しようとしています。多次元配列ディレクトリマップ

私はここまでだ:

function dirtree($dir, $regex = '', $ignoreEmpty = false) 
{ 
    if (!$dir instanceof DirectoryIterator) { 
     $dir = new DirectoryIterator((string) $dir); 
    } 
    $dirs = array(); 
    $files = array(); 
    foreach ($dir as $node) { 
     if ($node->isDir() && !$node->isDot()) { 
      $tree = dirtree($node->getPathname(), $regex, $ignoreEmpty); 
      if (!$ignoreEmpty || count($tree)) { 
       $dirs[$node->getFilename()] = $tree; 
      } 
     } elseif ($node->isFile()) { 
      $name = $node->getFilename(); 
      if ('' == $regex || preg_match($regex, $name)) { 
       $files[] = $name; 
      } 
     } 
    } 
    asort($dirs); 
    sort($files); 
    return array_merge($dirs, $files); 
} 

をしかし、私は、フォルダ名の代わりに、インデックス0,1 .etcを得るの問題を抱えています。 これは私のディレクトリに数字の名前があるためです

Array 
(
    [0] => Array // 0 should be the folder name 
     (
      [0] => m_109225488_1.jpg 
      [1] => t_109225488_1.jpg 
     ) 

    [1] => Array 
     (
      [0] => m_252543961_1.jpg 
      [1] => t_252543961_1.jpg 
     ) 
+0

あなたがここに '' $ var_dump' dirs'、 '$ files'をと期待される出力を追加することはできますか? –

+0

Hmm ... 'array_merge'はどうやって動いていませんか?私はあなたのコードを実行すると、期待通りに名前でキーを付けられたディレクトリを取得します。 'array_merge'は文字列キーを保持するはずです... –

+0

どうやら、私のディレクトリに数字の名前があったからです...私の答えのコメントのおかげで、そうでなければ私は質問に入れました。 – Alex

答えて

1

ソリューションは、おかげでかなり簡単だった:

function dirtree($dir, $regex = '', $ignoreEmpty = false) 
{ 
    if (!$dir instanceof DirectoryIterator) { 
     $dir = new DirectoryIterator((string) $dir); 
    } 
    $dirs = array(); 
    $files = array(); 
    foreach ($dir as $node) { 
     if ($node->isDir() && !$node->isDot()) { 
      $tree = dirtree($node->getPathname(), $regex, $ignoreEmpty); 
      if (!$ignoreEmpty || count($tree)) { 
       $dirs[$node->getFilename()] = $tree; 
      } 
     } elseif ($node->isFile()) { 
      $name = $node->getFilename(); 
      if ('' == $regex || preg_match($regex, $name)) { 
       $files[] = $name; 
      } 
     } 
    } 
    return $dirs + $files; 
} 

Merge array without loss key index

代わりのarray_mergeは単に$dirs + $files

潜在的な解決策を(潜在的な問題は、ロジャー・ジーによって指摘)を行いますより良い解決策?

function dirtree($dir, $regex = '', $ignoreEmpty = false) 
{ 
    if (!$dir instanceof DirectoryIterator) { 
     $dir = new DirectoryIterator((string) $dir); 
    } 
    $filedata = array(); 
    foreach ($dir as $node) { 
     if ($node->isDir() && !$node->isDot()) { 
      $tree = dirtree($node->getPathname(), $regex, $ignoreEmpty); 
      if (!$ignoreEmpty || count($tree)) { 
       $filedata[$node->getFilename()] = $tree; 
      } 
     } elseif ($node->isFile()) { 
      $name = $node->getFilename(); 
      if ('' == $regex || preg_match($regex, $name)) { 
       $filedata[] = $name; 
      } 
     } 
    } 
    return $filedata; 
} 
+0

解決策を共有してくれてありがとう、私は1つを解明しようとしていた。あなたのフォルダ名に数字の名前があったのでしょうか? –

+0

彼らはそうしました、そして、それらはあなたがそれに言及して今働かなかった唯一のものでした、おそらく最初の場所の原因でした。 – Alex

+0

注意: '0'または' 1'または任意の数値インデックスという名前のディレクトリがあると、配列共用時に除外されるため、ファイルによってはリストに表示されないことがあります。 PHPの '+'演算子は値ではなくキーの和集合です。左オペランドが右オペランドよりも優先されます。つまり、右オペランドの要素は無視されます。以前の 'array_merge'の例では、これは問題ではありませんでした。 'array_merge'のドキュメントは、数字キーが上書きされないことを示しています。 –

0

あなたが探しているものは、アスコルートの代わりにksortです。

<html> 
<body> 
<?php 
function dirtree($dir, $regex = '', $ignoreEmpty = false) 
{ 
    if (!$dir instanceof DirectoryIterator) { 
     $dir = new DirectoryIterator((string) $dir); 
    } 
    $dirs = array(); 
    $files = array(); 
    foreach ($dir as $node) { 
     if ($node->isDir() && !$node->isDot()) { 
      $tree = dirtree($node->getPathname(), $regex, $ignoreEmpty); 
      if (!$ignoreEmpty || count($tree)) { 
       $dirs[$node->getFilename()] = $tree; 
      } 
     } elseif ($node->isFile()) { 
      $name = $node->getFilename(); 
      if ('' == $regex || preg_match($regex, $name)) { 
       $files[] = $name; 
      } 
     } 
    } 
    ksort($dirs); 
    sort($files); 
    return array_merge($dirs, $files); 
} 
?> 
<body> 
<pre> 
<?=var_dump(dirtree(getcwd());?> 
</pre> 
</body> 
</html> 

これは作業を行います。 しかし、前述したように、より良い解決策は、このようなディレクトリとファイルを区切るために、次のようになります。あなたが潜在的に既存のファイルを上書きすることができるので、アレイ組合操作を使用

<html> 
<body> 
<?php 
class DirNode { 
    public $name; 
    public $dirs=[]; 
    public $files=[]; 

    public function DirNode($dirName) { 
     $this->name = $dirName; 
    } 

    public function printDir($prefix="") { 
     echo($prefix.$this->name."\n"); 
     foreach($this->dirs as $dir=>$subDir) { 
      echo($prefix.$dir."\n"); 
      $subDir->printDir($prefix." "); 
      echo("\n"); 
     } 
     foreach($this->files as $file) { 
      echo($prefix.$file."\n"); 
     } 
    } 
} 

function dirtree($dir, $regex = '', $ignoreEmpty = false) 
{ 
    if (!$dir instanceof DirectoryIterator) { 
     $dir = new DirectoryIterator((string) $dir); 
    } 
    $directory = new DirNode($dir); 
    foreach ($dir as $node) { 
     if ($node->isDir() && !$node->isDot()) { 
      $tree = dirtree($node->getPathname(), $regex, $ignoreEmpty); 
      if (!$ignoreEmpty || count($tree)) { 
       $directory->dirs[$node->getFilename()] = $tree; 
      } 
     } elseif ($node->isFile()) { 
      $name = $node->getFilename(); 
      if ('' == $regex || preg_match($regex, $name)) { 
       $directory->files[] = $name; 
      } 
     } 
    } 
    ksort($directory->dirs); 
    sort($directory->files); 
    return $directory; 
} 

$dirfiles = dirtree(getcwd().'/..'); 

echo("<pre>"); 
echo($dirfiles->printDir()); 
echo("</pre>"); 

?> 
</body> 
</html> 
+0

これは問題ではなかった... – Alex

1

は危険です。

a  <-- directory 
├── 0 <-- directory (empty) 
├── b <-- regular file 
└── c <-- directory 
    └── d <-- regular file 

ここで、配列ユニオンを使用して操作を実行することを検討してください。次の結果が得られます。

array(2) { 
    [0]=> 
    array(0) { 
    } 
    ["c"]=> 
    array(1) { 
    [0]=> 
    string(1) "d" 
    } 
} 

通常のファイルbはありません。これは、配列連合操作が、通常のファイルを含む右オペランドからの0インデックスを超える既存の0インデックスを好むためです。

質問またはに記載されている元の実装には、有効なファイルシステム名(例::files:)が含まれていないファイルに対して特殊なバケットを使用します。これは、プラットフォームに応じて選択することができます。

元の実装の場合、値がis_arrayまたはis_scalarの値を呼び出すことによって、インデックスがディレクトリか通常のファイルかを判断できます。ディレクトリ配列はarray_mergeの最初のパラメータであるため、ディレクトリインデックスは増分されず、常に正しいディレクトリ名を参照することが保証されます。ここで

は、あなただけのディレクトリ名を決定することができる方法は次のとおりです。

function getDirectoryNames($result) { 
    $ds = []; 
    foreach ($result as $key => $value) { 
     if (is_array($value)) { 
      $ds[] = $key; 
     } 
    } 
    return $ds; 
}