Intereting Posts
xampp apache не работает err сообщение api ms win missing Как динамически генерировать XML-файл с помощью PHP? Предотвращение незанятого состояния при загрузке (веб-приложение на iOS) Ошибка Parse error: синтаксическая ошибка, неожиданный T_STRING, ожидающий T_CONSTANT_ENCAPSED_STRING PHP-асинхронный mysql-запрос конвертировать персидские / арабские цифры на английские номера PHP: mysql_fetch_array () ожидает, что параметр 1 будет ресурсом, boolean given fgetcsv () катит символы с диакритикой (т.е. не-ASCII) – как исправить? Сортировка по группам Regex в PHP getimagesize не может получить размер удаленных веб-файлов с PHP версии 5.3.29 XDebug, как отключить удаленную отладку для одного .php-файла? Постоянное обновление текстовой игры PHP PHP Native DOMDocument и простой DOM Parser – существует ли ограничение по размеру? Как шифровать / расшифровывать AES с помощью Libsodium-PHP Почему var_dump не работает с объектами DomDocument, а print ($ dom-> saveHTML ())?

Структура каталога списка PHP и исключить некоторые каталоги

У меня есть этот код PHP:

$rootpath = '../admin/'; $inner = new RecursiveDirectoryIterator($rootpath); $fileinfos = new RecursiveIteratorIterator($inner); foreach ($fileinfos as $pathname => $fileinfo) { $pathname2 = substr($pathname,2); $sql = "SELECT * from admin_permissions where page_name = '$pathname2'"; $rs = mysql_query($sql,$conn); if (mysql_num_rows($rs) == 0) { if (!$fileinfo->isFile()) continue; $sql2 = "INSERT into admin_permissions (page_name) values ('$pathname2')"; $rs2 = mysql_query($sql2,$conn); echo "$pathname<br>"; } } 

Это отображает мою структуру каталогов и вставляет каталоги и имена файлов в базу данных (удаление первых двух символов .. ).

Поскольку RecursiveDirectoryIterator выполняет итерацию по всем файлам во всех каталогах, как я могу исключить целые каталоги, включая все файлы внутри них?

Related of "Структура каталога списка PHP и исключить некоторые каталоги"

По сути, мой ответ не сильно отличается от ответа Томаса . Тем не менее, он не получает несколько правильных вещей:

  • Семантика, правильная для RecursiveCallbackFilterIterator требует, чтобы вы возвращали значение true для рекурсии в подкаталоги.
  • Он не пропускает . и .. каталоги внутри каждого подкаталога
  • Его проверка in_array не совсем делает то, что он ожидает

Итак, я написал этот ответ. Это будет работать правильно, предполагая, что я понимаю, чего вы хотите:

Изменить: с тех пор он исправил 2 из этих трех вопросов; третья не может быть проблемой из-за того, как он написал свой условный чек, но я не совсем уверен.

 <?php $directory = '../admin'; // Will exclude everything under these directories $exclude = array('.git', 'otherDirToExclude'); /** * @param SplFileInfo $file * @param mixed $key * @param RecursiveCallbackFilterIterator $iterator * @return bool True if you need to recurse or if the item is acceptable */ $filter = function ($file, $key, $iterator) use ($exclude) { if ($iterator->hasChildren() && !in_array($file->getFilename(), $exclude)) { return true; } return $file->isFile(); }; $innerIterator = new RecursiveDirectoryIterator( $directory, RecursiveDirectoryIterator::SKIP_DOTS ); $iterator = new RecursiveIteratorIterator( new RecursiveCallbackFilterIterator($innerIterator, $filter) ); foreach ($iterator as $pathname => $fileInfo) { // do your insertion here } 

Я предлагаю использовать RecursiveCallbackFilterIterator.

 $directory = '../admin/'; $filter = array('.git'); $fileinfos = new RecursiveIteratorIterator( new RecursiveCallbackFilterIterator( new RecursiveDirectoryIterator( $directory, RecursiveDirectoryIterator::SKIP_DOTS ), function ($fileInfo, $key, $iterator) use ($filter) { return $fileInfo->isFile() || !in_array($fileInfo->getBaseName(), $filter); } ) ); foreach($fileinfos as $pathname => $fileinfo) { //... } 

Мое предложение – попробовать использовать библиотеку поиска Symfony, так как это намного облегчает и легко устанавливается через композитор, вот документы

http://symfony.com/doc/current/components/finder.html

и вот простой пример чего-то похожего на то, что, я думаю, вы просите

 <?php use Symfony\Component\Finder\Finder; /** * @author Clark Tomlinson <fallen013@gmail.com> * @since 12/6/13, 12:52 PM * @link http://www.clarkt.com * @copyright Clark Tomlinson © 2013 * */ require_once('vendor/autoload.php'); $finder = new Finder(); $directories = $finder->directories() ->in(__DIR__) ->ignoreDotFiles(true) ->exclude(array('one', 'two', 'three', 'four')) ->depth(0); foreach ($directories as $dir) { echo '<pre>'; print_r($dir->getRealPath()); echo '</pre>'; } 

Этот пример вернет все каталоги, не пересекая их, чтобы изменить это изменение или удалить глубину.

Чтобы все файлы в этом каталоге делали что-то похожее на это

 <?php use Symfony\Component\Finder\Finder; /** * @author Clark Tomlinson <fallen013@gmail.com> * @since 12/6/13, 12:52 PM * @link http://www.clarkt.com * @copyright Clark Tomlinson © 2013 * */ require_once('vendor/autoload.php'); $finder = new Finder(); $directories = $finder->directories() ->in(__DIR__) ->ignoreDotFiles(true) ->exclude(array('one', 'two', 'three', 'four')) ->depth(0); foreach ($directories as $dir) { $files = $finder->files() ->ignoreDotFiles(true) ->in($dir->getRealPath()); foreach ($files as $file) { echo '<pre>'; print_r($file); echo '</pre>'; } } 

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

Во-первых, вы создаете функцию, которая получает каталог, который вы хотите изучить, и необязательный массив или исключенные имена файлов

 function getFiles($dir , $exclude=array()){ $acceptedfiles=array(); $handle=opendir($dir ); //reads the filenames, one by one while ($file = readdir($handle)) { if ($file!="." && $file!=".." && is_file($file) && !in_array($file, $exclude)) $acceptedfiles[]=$file; } closedir($handle); return $acceptedfiles; } 

Теперь вам просто нужно вызвать функцию

 $files= getFiles($rootpath) ; 

или если вы хотите исключить некоторые файлы, если они существуют, вы можете позвонить

 $files= getFiles($rootpath, array(".htaccess","otherfile", "etc")) ; 

Вы можете использовать RecursiveFilterIterator для фильтрации dirs, а в петле fooreach вы только принимаете dirs.

 class MyDirFilter extends RecursiveFilterIterator { public function accept() { $excludePath = array('exclude_dir1', 'exclude_dir2'); foreach($excludePath as $exPath){ if(strpos($this->current()->getPath(), $exPath) !== false){ return false; } } return true; } } $rootpath = '../admin/'; $dirIterator = new RecursiveDirectoryIterator($rootpath); $filter = new MyDirFilter($dirIterator); $fileinfos = new RecursiveIteratorIterator($filter); foreach($fileinfos as $pathname => $fileinfo) { // only accepted dirs in loop } 

Я бы сделал это так:

 $excludes = array( 'files' => array('file1.ext','file2.ext','fileN.ext'), 'dirs' => array('dir1','dir2','dirN') ); foreach ($directories as $current_dir) { if (!in_array($current_dir,$excludes['dirs'])) { // directory method foreach ($files as $current_file) { if (!in_array($current_file,$excludes['files'])) { // files method } } } } 

Если я правильно догадаюсь, вы просто хотите добавить базовый путь для файлов, а не для каталога.

Просто используйте для проверки функцию is_file в вашем foreach

Например

 foreach ($fileinfos as $pathname => $fileinfo) { if (!is_file($pathname)) { continue;// next step } $pathname2 = substr($pathname,2); ... }