2009-12-12 2 views
1

Я пытаюсь использовать рекурсивный итератор каталогов PHP для поиска файлов php и html, чтобы перечислить их по дате. Код используется следующим образом:Как сделать только выбранные папки с помощью Итератора PHP?

 $filelist = array(); 
    $iterator = new RecursiveDirectoryIterator($this->_jrootpath); 
    foreach(new RecursiveIteratorIterator($iterator) as $file) { 
     if (!$file->isDir()) { 
      if (preg_match("/.(html|htm|php)$/", $file->getFilename())) { 
       $filelist[$file->getPathname()] = $file->getMTime(); 
      } 
     } 
    } 
    arsort($filelist); 
    foreach ($filelist as $key => $val) { 
     $resultoutput .= '   <tr> 
             <td class="filepath">'.$key.'</td> 
             <td class="filedate">'.date("d-m-Y H:i:s",$val).'</td> 
            </tr>'; 
    } 

Вышеприведенные работает, но мне нужно, чтобы ограничить итерацию к определенным папкам. Этот скрипт начнется в родительской папке, где я ожидаю, что некоторые подпапки, такие как «администратор», «компоненты», «модули», «плагины» и «шаблоны» (другими словами, стандартные папки установки Joomla). Я также ожидаю несколько файлов в родительской папке, например «index.php». Эти файлы и папки должны быть повторены (честно говоря, пишу это, я не уверен, что сама родительская папка повторяется моим кодом!). Однако возможно, что родительская папка также содержит другие подпапки, которые не должны повторяться. Это могут быть подпапки для поддоменов или доменов аддонов, названных, например, «mysub» и «myaddon.com». Есть две причины, по которым я хочу пропустить любую папку, кроме обычных установочных папок Joomla. Во-первых, мне не нужно знать о файлах в других папках. Более того, повторение всех папок может занять столько времени и ресурсов, что я получаю 500 страниц ошибок.

Мой вопрос в том, как лучше всего изменить свой код, чтобы убедиться, что правые папки исключены из итерации и включены в нее? Я видел примеры итератора в Интернете, проверяющие имя каталога, но это не помогает мне, потому что мне нужно только проверить имена папок второго уровня (что означает только вложенную папку высшего уровня в пути, таком как parent/secondlevel/noneedtocheck /file.php).

ответ

0

Вы можете попробовать использовать RecursiveRegexIterator.

EDIT Это ваш пример использования RecursiveRegexIterator:

$filelist = array(); 
$iterator = new RecursiveDirectoryIterator($this->_jrootpath); 
foreach(new RecursiveRegexIterator($iterator, '/\.(html|htm|php)$/') as $file) { 
    if (!$file->isDir()) { 
     $filelist[$file->getPathname()] = $file->getMTime(); 
    } 
} 
arsort($filelist); 
foreach ($filelist as $key => $val) { 
    $resultoutput .= '      <tr> 
                      <td class="filepath">'.$key.'</td> 
                      <td class="filedate">'.date("d-m-Y H:i:s",$val).'</td> 
                    </tr>'; 
} 

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

EDIT2: Ой, это на самом деле не отвечает на ваш вопрос. По какой-то причине я думал, что речь идет только о рекурсивном материале. Это просто более элегантное решение для обработки файлов, но это не решает вашу проблему, извините. Вы, вероятно, должны сочетать это с одним из других ответов.

+0

Это может быть лучшим решением, но я действительно не хорошо ни с регулярное выражение или экспериментирование с почти недокументированными классами. Кажется, что итераторы - это мощные инструменты, но комментарии пользователя с хорошими примерами все еще отсутствуют в руководстве. –

+0

У вас есть регулярное выражение в вашем примере кода. Думаю, это, вероятно, сработает. Else, я хотел бы помочь вам;) – Franz

+0

Спасибо! Это регулярное выражение было высотой моего достижения. Мне удалось заставить его работать с кодом, который я опубликовал, но я хотел бы знать, как это сделать лучше с помощью regexiterator - после этого я хорошо пишу код, чтобы узнать. Я озадачен тем, как это будет выбирать правильный уровень папки для проверки, но я полагаю, что хорошее регулярное выражение будет иметь дело с этим. –

0
$filelist = array(); 

// сделать массив ExcludeDirs $ ExcludeDirs = массив ("/ Var/WWW/Joomla/администратор /");

$iterator = new RecursiveDirectoryIterator($this->_jrootpath); 
    foreach(new RecursiveIteratorIterator($iterator,RecursiveIteratorIterator::CHILD_FIRST) as $file) { 
    if($file->getPathname() == excludeDirs[0]) 
     continue; 
    if (!$file->isDir()) { 
        if (preg_match("/.(html|htm|php)$/", $file->getFilename())) { 
          $filelist[$file->getPathname()] = $file->getMTime(); 
        } 
      } 
    } 
    arsort($filelist); 
    foreach ($filelist as $key => $val) { 
      $resultoutput .= '<tr> 
      <td class="filepath">'.$key.'</td> 
      <td class="filedate">'.date("d-m-Y H:i:s",$val).'</td> 
      </tr>'; 
    } 
+0

Я не пробовал это, но если я правильно понял итерацию, то путь (полный путь плюс имя файла с расширением) нужно разбить по частям, чтобы найти первый каталог после _jrootpath, который должен был бы соответствовать одному of excludeDirs (на самом деле я предполагаю, что они будут includeDirs). Возможно, тогда было бы лучше использовать RecursiveRegexIterator. –

0

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

$filelist = array(); 
    $filelist[$this->_jrootpath.DS.'index.php'] = date("d-m-Y H:i:s",filemtime($this->_jrootpath.DS.'index.php')); 
    $filelist[$this->_jrootpath.DS.'index2.php'] = date("d-m-Y H:i:s",filemtime($this->_jrootpath.DS.'index2.php')); 
    $joomlafolders = array($this->_jrootpath.DS.'administrator', $this->_jrootpath.DS.'cache', $this->_jrootpath.DS.'components', $this->_jrootpath.DS.'images', $this->_jrootpath.DS.'includes', $this->_jrootpath.DS.'language', $this->_jrootpath.DS.'libraries', $this->_jrootpath.DS.'logs', $this->_jrootpath.DS.'media', $this->_jrootpath.DS.'modules', $this->_jrootpath.DS.'plugins', $this->_jrootpath.DS.'templates', $this->_jrootpath.DS.'tmp', $this->_jrootpath.DS.'xmlrpc'); 
    foreach ($joomlafolders as $folder) { 
     $iterator = new RecursiveDirectoryIterator($folder); 
     foreach(new RecursiveIteratorIterator($iterator) as $file) { 
      if (!$file->isDir()) { 
       if (preg_match("/.(html|htm|php)$/", $file->getFilename())) { 
        $filelist[$file->getPathname()] = $file->getMTime(); 
       } 
      } 
     } 
    } 
    arsort($filelist); 
    foreach ($filelist as $key => $val) { 
     $resultoutput .= '   <tr> 
             <td class="filepath">'.$key.'</td> 
             <td class="filedate">'.date("d-m-Y H:i:s",$val).'</td> 
            </tr>'; 
    } 
1

нет нет! вы хотите что-то вроде:

<?php 
class FilteredRecursiveDirectoryIterator extends FilterIterator 
{ 
    public function __construct($path) 
    { 
     parent::__construct(new RecursiveDirectoryIterator($path)); 
    } 
    public function accept() 
    { 
     if($this->current()->isFile() and in_array($this->getExtention(), array('html', 'php'))) 
      return true; 

     return false; 
    } 

    private function getExtention() 
    { 
     return end(explode('.', $this->current()->getFilename())); 
    } 
} 

где метод принимает() делает всю фильтрацию для вас. Я не проверял это, но я уверен, что это хорошо.)

0

Обычно вы используете RecursiveIteratorIterator для разрешения «рекурсивности» в RecursiveDirectoryIterator.A RecursiveIteratorIterator - это просто Iterator, который может использоваться как любой другой, с которым вы, возможно, уже знакомы. Сюда входит использование FilterIterator. В PHP 5.4, похоже, что (CallbackIterator новый)

<?php 
$directories = new CallbackIterator(
    new RecursiveIteratorIterator(
     new RecursiveDirectoryIterator('path/to/directory') 
    ), 
    function($current) { 
     return $current->isDir(); 
    } 
); 

foreach ($directories as $directory) { 
    ... 
} 

Для PHP < 5.4 необходимо реализовать CallbackIterator себя

<?php 
class CallbackIterator extends FilterIterator 
{ 
    private $callback; 

    public function __construct(Traversable $iterator, $callback) 
    { 
     $this->callback = $callback; 
    } 

    public function accept() 
    { 
     return call_user_func($this->callback, $this->current()); 
    } 
} 
+0

Просто небольшая коррекция: класс PHP 5.4 называется ['CallbackFilterIterator'] (http://php.net/CallbackFilterIterator), а не' CallbackIterator'. Этот все еще отсутствует;) – hakre

 Смежные вопросы

  • Нет связанных вопросов^_^