Я установил базовый скрипт, который публикует массив путей для поиска файлов шаблонов внутри них; в настоящее время он ищет только два уровня, и у меня возникают некоторые проблемы, когда я пытаюсь разобраться в логике расширенного цикла для перебора всех дочерних каталогов, пока длина не станет равна 0.
Так что, если у меня есть такая структура:
./components
./components/template.html
./components/template2.html
./components/side/template.html
./components/side/template2.html
./components/side/second/template.html
./components/side/second/template2.html
./components/side/second/third/template.html
./components/side/second/third/template2.html
Это только поиск в «боковом» каталоге для файлов .html, когда в идеале я хочу, чтобы он проверял все дочерние каталоги и переданный каталог для файлов .html. Вот мой рабочий код:
<?php
function getFiles($path){
$dh = opendir($path);
foreach(glob($path.'/*.html') as $filename){
$files[] = $filename;
}
if (isset($files)) {
return $files;
}
}
foreach ($_POST as $path) {
foreach (glob($path . '/*' , GLOB_ONLYDIR) as $secondLevel) {
$files[] = getFiles($secondLevel);
}
$files[] = getFiles($path);
}
sort($files);
print_r(json_encode($files));
?>
В PHP есть идеальное решение для вас.
// Construct the iterator
$it = new RecursiveDirectoryIterator("/components");
// Loop through files
foreach(new RecursiveIteratorIterator($it) as $file) {
if ($file->getExtension() == 'html') {
echo $file;
}
}
PHP 5 вводит итераторы для быстрой итерации по многим элементам.
Ты можешь использовать RecursiveDirectoryIterator рекурсивно перебирать каталоги.
Ты можешь использовать RecursiveIteratorIterator на результат, чтобы иметь плоский вид результата.
Ты можешь использовать RegexIterator на результат для фильтрации на основе регулярного выражения.
$directory_iterator = new RecursiveDirectoryIterator('.');
$iterator = new RecursiveIteratorIterator($directory_iterator);
$regex_iterator = new RegexIterator($iterator, '/\.php$/');
$regex_iterator->setFlags(RegexIterator::USE_KEY);
foreach ($regex_iterator as $file) {
echo $file->getPathname() . PHP_EOL;
}
С итераторами есть много способов сделать то же самое, вы также можете использовать FilterIterator (см. пример на странице)
Например, если вы хотите выбрать файлы, измененные на этой неделе, вы можете использовать следующее:
$directory_iterator = new RecursiveDirectoryIterator('.');
$iterator = new RecursiveIteratorIterator($directory_iterator);
class CustomFilterIterator extends FilterIterator {
function accept() {
$current=$this->getInnerIterator()->current();
return ($current->isFile()&&$current->getMTime()>time()-3600*24*7);
}
}
$filter_iterator=new CustomFilterIterator($iterator);
foreach ($filter_iterator as $file) {
echo $file->getPathname() . PHP_EOL;
}
Другое решение — использование компонента Finder от Symfony. Это проверенный и проверенный код. Посмотрите на это здесь: http://symfony.com/doc/current/components/finder.html
Вот рабочий код, который сканирует данный каталог $ dir и все его подкаталоги на любые уровни и возвращает список HTML-файлов и папок, содержащих их.
<?php
function find_all_files($dir)
{
if(!is_dir($dir)) return false;
$pathinfo = '';$root = scandir($dir);
foreach($root as $value)
{
if($value === '.' || $value === '..') {continue;}if(is_file("$dir/$value")) {
$pathinfo = pathinfo($dir.'/'.$value);
if($pathinfo['extension'] == 'html') {
$result[]="$dir/$value";}
continue;
}
foreach(find_all_files("$dir/$value") as $value)
{
$result[]=$value;
}
}
return $result;
}
//call function
$res = find_all_files('physical path to folder');
print_r($res);
?>
Универсальный поиск файлов в папке, подпапке:
function dirToArray($dir,$file_name) {
$result = array();
$cdir = scandir($dir);
foreach ($cdir as $key => $value)
{
if (!in_array($value,array(".","..")))
{
if (is_dir($dir . DIRECTORY_SEPARATOR . $value))
{
$result[$value] = dirToArray($dir . DIRECTORY_SEPARATOR . $value,$file_name);
}
else
{
if($value == $file_name){
$result[] = $value;
}
}
}
}
return $result;
}
define('ROOT', dirname(__FILE__));
$file_name = 'template.html';
$tree = dirToArray(ROOT,$file_name);
echo "<pre>".print_r($tree,1)."</pre>";
ВЫХОД :
Array
(
[components] => Array
(
[side] => Array
(
[second] => Array
(
[0] => template.html
[third] => Array
(
[0] => template.html
)
)
[0] => template.html
)
[0] => template.html
)
[0] => template.html
)
Альтернатива моего предыдущего ответа:
$dir = 'components';
function getFiles($dir, &$results = array(), $filename = 'template.html'){
$files = scandir($dir);
foreach($files as $key => $value){
$path = realpath($dir.'/'.$value);
if(!is_dir($path)) {
if($value == $filename)
$results[] = $path;
} else if($value != "." && $value != "..") {
getFiles($path, $results);
}
}
return $results;
}
echo '<pre>'.print_r(getFiles($dir), 1).'</pre>';
ВЫХОД :
Array
(
[0] => /web/practise/php/others/test7/components/side/second/template.html
[1] => /web/practise/php/others/test7/components/side/second/third/template.html
[2] => /web/practise/php/others/test7/components/side/template.html
[3] => /web/practise/php/others/test7/components/template.html
)
Вот общее решение:
function parseDir($dir, &$files=array(), $extension=false){
if(!is_dir($dir)){
$info = pathinfo($dir);
// add all files if extension is set to false
if($extension === false || (isset($info['extension']) && $info['extension'] === $extension)){
$files[] = $dir;
}
}else{
if(substr($dir, -1) !== '.' && $dh = opendir($dir)){
while($file = readdir($dh)){
parseDir("$dir/$file", $files, $extension);
}
}
}
}
$files = array();
parseDir('components', $files, 'html');
var_dump($files);
ВЫХОД
php parseDir.php
array(7) {
[0]=>
string(25) "components/template2.html"[1]=>
string(29) "components/side/template.html"[2]=>
string(30) "components/side/template2.html"[3]=>
string(36) "components/side/second/template.html"[4]=>
string(37) "components/side/second/template2.html"[5]=>
string(42) "components/side/second/third/template.html"[6]=>
string(43) "components/side/second/third/template2.html"}