2016-02-28 2 views
3

У меня есть следующий очень простой код RecursiveDirectoryIterator:RecursiveDirectoryIterator в PHP, получая каждый каталог дважды в Еогеаспе

$dir = new RecursiveDirectoryIterator('/Users/yivi/test/', RecursiveDirectoryIterator::KEY_AS_PATHNAME); 

$iter = new RecursiveIteratorIterator($dir); 

foreach ($iter as $item) { 
    if ($item->isDir()) { 
     echo $item->getPath() . "\n"; 
     $countd ++; 
    } else { 
     $count++; 
    } 
} 
echo "$count files and $count directories"; 

Но производит следующий вывод:

/Users/yivi/Sites/test 
/Users/yivi/Sites/test 
/Users/yivi/Sites/test/01 
/Users/yivi/Sites/test/01 
/Users/yivi/Sites/test/02 
/Users/yivi/Sites/test/02 
/Users/yivi/Sites/test/03 
/Users/yivi/Sites/test/03 
/Users/yivi/Sites/test/03/ab 
/Users/yivi/Sites/test/03/ab 
/Users/yivi/Sites/test/03/cd 
/Users/yivi/Sites/test/03/cd 

40 files and 12 directories 

К тому времени я выйти из I контура подсчитал каждый каталог дважды (я получаю двойной листинг и $ countd равен 12, а не 6).

Почему это так? Как этого избежать?

Я попытался использовать RecursiveDirectoryIterator::SKIP_DOTS в качестве флага, но затем он пропускает все каталоги (но делает подсчет файлов).

(PHP 5,5)

+0

Я лично не знаю, как исправить это в ядре класса, но обойти его (если вы спешите) выводится в массив, тогда 'array_unique()' – Rasclatt

+0

Yup, и я могу подумайте о других быстрых исправлениях, но в основном я хотел бы понять это поведение. Спасибо, в любом случае! – yivi

+0

Да, я тебя слышу. Я столкнулся с такими странными поведениями, как это с помощью итераторов, и я просто исправляю их быстро и грязно, поэтому мне также интересно, как исправить это конкретное поведение на уровне класса. – Rasclatt

ответ

1

TL; DR Использование RecursiveIteratorIterator::SELF_FIRST в режиме итерации, наряду с RecursiveDirectoryIterator::SKIP_DOTS флагом.


Вы видите две линии, потому что $item значение для «» и "..", и были права попробовать использовать SKIP_DOTS, поскольку вы, скорее всего, захотите пропустить эти элементы.

Однако поведение по умолчанию для RecursiveIteratorIterator состоит в том, чтобы перебирать только элементы «листа» (т. Е. Элементы, которые не содержат больше элементов), а не все, эффективно пропуская каталоги.

Итак, вы должны сообщить, что RecursiveIteratorIterator использует другой режим, кроме режима «только листья» по умолчанию: один из «самого первого» или «первый ребенок».

$iter = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::SELF_FIRST); 

Назад к исходному коду, вы можете увидеть, что происходит на вторя $item->getPathname() (или просто вторя $item будет работать здесь). Это покажет вам «точечные каталоги», которые вам нужно пропустить.

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