어떻게 RecursiveIteratorIterator
작동합니까?
PHP 매뉴얼에는 많이 문서화되거나 설명되어 있지 않습니다. IteratorIterator
과 의 차이점은 무엇입니까 RecursiveIteratorIterator
?
어떻게 RecursiveIteratorIterator
작동합니까?
PHP 매뉴얼에는 많이 문서화되거나 설명되어 있지 않습니다. IteratorIterator
과 의 차이점은 무엇입니까 RecursiveIteratorIterator
?
RecursiveIteratorIterator
작동 하는지 묻는다면 이미 어떻게 IteratorIterator
작동 하는지 이해 했습니까? 기본적으로 동일하고 둘이 소비하는 인터페이스 만 다릅니다. 그리고 몇 가지 예제에 더 관심이 있습니까? 아니면 기본 C 코드 구현의 차이점을보고 싶습니까?
IteratorIterator
지도 Iterator
및 IteratorAggregate
에 Iterator
어디에 REcusiveIteratorIterator
사용됩니다 recusivly 트래버스합니다RecursiveIterator
답변:
RecursiveIteratorIterator
구체적인 Iterator
구현 트리 순회 입니다. 이를 통해 프로그래머는 RecursiveIterator
인터페이스 를 구현하는 컨테이너 객체를 순회 할 수 있습니다. 반복기 의 일반 원칙, 유형, 의미론 및 패턴은 Wikipedia의 Iterator를 참조하세요 .
차이에 IteratorIterator
있는 콘크리트입니다 Iterator
선형 순서 (기본적으로 모든 종류의 수용 구현하는 객체 통과 Traversable
생성자에서이)는이 RecursiveIteratorIterator
의 모든 노드에 걸쳐 반복 할 수 있습니다 주문 트리 객체와 생성자는 걸립니다 RecursiveIterator
.
간단히 말해서 : RecursiveIteratorIterator
트리 IteratorIterator
를 반복 할 수 있고 목록을 반복 할 수 있습니다. 곧 아래의 몇 가지 코드 예제를 통해이를 보여 드리겠습니다.
기술적으로 이것은 모든 노드의 자식 (있는 경우)을 순회하여 선형성을 벗어나 작동합니다. 이것은 정의에 따라 노드의 모든 자식이 다시 RecursiveIterator
. Iterator
그런 다음 최상위 수준 RecursiveIterator
은 깊이별로 다른 s 를 내부적으로 스택하고 Iterator
순회 를 위해 현재 활성 하위에 대한 포인터를 유지합니다 .
이를 통해 트리의 모든 노드를 방문 할 수 있습니다.
기본 원칙은 with와 동일합니다 IteratorIterator
. 인터페이스는 반복 유형을 지정하고 기본 반복기 클래스는 이러한 의미를 구현합니다. 아래의 예와 비교해 보면, 선형 루핑의 경우 foreach
일반적으로 새로 정의 할 필요가없는 한 구현 세부 사항에 대해 많이 생각하지 않습니다 Iterator
(예 : 일부 구체적인 유형 자체가 구현하지 않는 경우 Traversable
).
재귀 탐색을 위해 - 당신이 사용하지 않는 한 사전 정의 된 Traversal
이미 재귀 탐색 반복 가지고 - 당신이 일반적으로 필요한 기존의 인스턴스를 RecursiveIteratorIterator
반복하거나 쓰기 재귀 탐색 반복 A는 그 Traversable
탐색 반복과의이 유형을 가지고 자신의 foreach
.
팁 : 하나 또는 다른 하나를 직접 구현하지 않았을 수 있으므로 차이점에 대한 실제 경험을 위해 수행 할 가치가있을 수 있습니다. 답변 끝에 DIY 제안이 있습니다.
요약하자면 기술적 차이점 :
IteratorIterator
어떤 걸리는 Traversable
선형 탐색을 위해, RecursiveIteratorIterator
더 구체적인 필요 RecursiveIterator
트리를 통해 루프를.IteratorIterator
주요 노출 Iterator
비아를 getInnerIerator()
, RecursiveIteratorIterator
현재의 액티브 서브를 제공 Iterator
해당 방법을 통해.IteratorIterator
완전히 부모 나 아이 같은 것을 인식하지, RecursiveIteratorIterator
뿐만 아니라 얻고 이송 어린이하는 방법을 알고있다.IteratorIterator
반복기 스택이 필요하지 않으며 RecursiveIteratorIterator
이러한 스택이 있으며 활성 하위 반복기를 알고 있습니다.IteratorIterator
선형성과 선택의 여지로 인해 수주가 RecursiveIteratorIterator
더 탐색하고 각 노드 당 결정하는 요구에 대한 선택의 여지가을 (를 통해 결정 모드 당RecursiveIteratorIterator
).RecursiveIteratorIterator
보다 많은 메서드가 IteratorIterator
있습니다.요약하면 : RecursiveIterator
는 자체 반복자 (즉,)에서 작동하는 구체적인 반복 유형 (트리를 반복)입니다 RecursiveIterator
. 이는와 동일한 기본 원칙 IteratorIerator
이지만 반복 유형이 다릅니다 (선형 순서).
이상적으로는 자신 만의 세트를 만들 수도 있습니다. 필요한 유일한 것은 반복자 Traversable
가 Iterator
또는을 통해 가능한 것을 구현 하는 것입니다 IteratorAggregate
. 그런 다음 foreach
. 예를 들어, 컨테이너 객체에 대한 반복 인터페이스와 함께 일종의 삼항 트리 순회 재귀 반복 객체.
그다지 추상적이지 않은 실제 사례를 살펴 보겠습니다. 인터페이스, 구체적인 반복기, 컨테이너 객체 및 반복 의미론 사이에서 이것은 그렇게 나쁜 생각이 아닐 수도 있습니다.
디렉토리 목록을 예로 들어 보겠습니다. 디스크에 다음 파일 및 디렉토리 트리가 있다고 가정하십시오.
선형 순서의 반복기는 최상위 폴더 및 파일 (단일 디렉토리 목록)을 순회하는 반면, 반복 반복기는 하위 폴더도 탐색하고 모든 폴더 및 파일 (하위 디렉토리 목록이있는 디렉토리 목록)을 나열합니다.
Non-Recursive Recursive
============= =========
[tree] [tree]
├ dirA ├ dirA
└ fileA │ ├ dirB
│ │ └ fileD
│ ├ fileB
│ └ fileC
└ fileA
IteratorIterator
디렉토리 트리를 순회 할 때 재귀가없는 것과 쉽게 비교할 수 있습니다 . 그리고 RecursiveIteratorIterator
재귀 목록에서 볼 수 있듯이 트리로 이동할 수 있습니다.
처음에는이 를 반복 할 수 DirectoryIterator
있는 구현 Traversable
을 가진 매우 기본적인 예제 :foreach
$path = 'tree';
$dir = new DirectoryIterator($path);
echo "[$path]\n";
foreach ($dir as $file) {
echo " ├ $file\n";
}
위의 디렉토리 구조에 대한 예제 출력은 다음과 같습니다.
[tree]
├ .
├ ..
├ dirA
├ fileA
보시다시피 이것은 아직 IteratorIterator
또는 RecursiveIteratorIterator
. 대신 인터페이스에서 foreach
작동하는 것만 사용 합니다 Traversable
.
foreach
기본적으로 선형 순서라는 반복 유형 만 알고 있기 때문에 반복 유형을 명시 적으로 지정할 수 있습니다. 언뜻보기에는 너무 장황 해 보일 수 있지만 데모 목적으로 (그리고 RecursiveIteratorIterator
나중에 더 잘 보이게 IteratorIterator
하기 위해) 디렉토리 목록에 대한 반복 유형을 명시 적으로 지정하여 선형 반복 유형을 지정할 수 있습니다 .
$files = new IteratorIterator($dir);
echo "[$path]\n";
foreach ($files as $file) {
echo " ├ $file\n";
}
이 예는 거의 차이 즉, 첫 번째와 동일한 $files
지금이다 IteratorIterator
위한 반복의 유형 Traversable
$dir
:
$files = new IteratorIterator($dir);
평소와 같이 반복 작업은 다음에 의해 수행됩니다 foreach
.
foreach ($files as $file) {
출력은 정확히 동일합니다. 그래서 무엇이 다른가요? 내에서 사용되는 개체는 다릅니다 foreach
. 첫 번째 예에서는 a DirectoryIterator
이고 두 번째 예에서는 IteratorIterator
. 이는 반복기가 갖는 유연성을 보여줍니다. 서로 교체 할 수 있으며 내부 코드 foreach
는 예상대로 계속 작동합니다.
하위 디렉터리를 포함하여 전체 목록을 가져 오겠습니다.
이제 반복 유형을 지정 했으므로 다른 유형의 반복으로 변경해 보겠습니다.
우리는 이제 첫 번째 레벨뿐만 아니라 전체 트리를 횡단해야한다는 것을 알고 있습니다. 단순하게 작동하려면 foreach
다른 유형의 반복자가 필요합니다 RecursiveIteratorIterator
.. 그리고 그 RecursiveIterator
인터페이스 가있는 컨테이너 객체에 대해서만 반복 할 수 있습니다 .
인터페이스는 계약입니다. 이를 구현하는 모든 클래스는 RecursiveIteratorIterator
. 이러한 클래스의 예는 RecursiveDirectoryIterator
의 재귀 변형과 같은입니다 DirectoryIterator
.
I-word로 다른 문장을 작성하기 전에 첫 번째 코드 예제를 살펴 보겠습니다.
$dir = new RecursiveDirectoryIterator($path);
echo "[$path]\n";
foreach ($dir as $file) {
echo " ├ $file\n";
}
이 세 번째 예제는 첫 번째 예제와 거의 동일하지만 몇 가지 다른 출력을 생성합니다.
[tree]
├ tree\.
├ tree\..
├ tree\dirA
├ tree\fileA
좋아, 그렇게 다르지는 않지만 이제 파일 이름 앞에 경로 이름이 포함되어 있지만 나머지도 비슷해 보입니다.
예제에서 알 수 있듯이 디렉토리 객체는 이미 RecursiveIterator
인터페이스를 구현하지만 아직 foreach
전체 디렉토리 트리를 순회 하기에는 충분하지 않습니다 . 이것이 RecursiveIteratorIterator
행동으로 오는 곳 입니다. 예 4 는 방법을 보여줍니다.
$files = new RecursiveIteratorIterator($dir);
echo "[$path]\n";
foreach ($files as $file) {
echo " ├ $file\n";
}
은 Using RecursiveIteratorIterator
대신 이전의 $dir
오브젝트하는 것 foreach
재귀 방식으로 모든 파일과 디렉토리를 통해 통과 할 수 있습니다. 그러면 이제 객체 반복 유형이 지정되었으므로 모든 파일이 나열됩니다.
[tree]
├ tree\.
├ tree\..
├ tree\dirA\.
├ tree\dirA\..
├ tree\dirA\dirB\.
├ tree\dirA\dirB\..
├ tree\dirA\dirB\fileD
├ tree\dirA\fileB
├ tree\dirA\fileC
├ tree\fileA
이것은 플랫과 트리 순회의 차이를 이미 보여 주어야합니다. 은 RecursiveIteratorIterator
요소의 목록으로 어떤 트리 구조를 탐색 할 수 있습니다. 더 많은 정보 (예 : 현재 반복이 발생하는 수준)가 있기 때문에 반복하는 동안 반복기 객체에 액세스 할 수 있습니다 (예 : 출력 들여 쓰기).
echo "[$path]\n";
foreach ($files as $file) {
$indent = str_repeat(' ', $files->getDepth());
echo $indent, " ├ $file\n";
}
그리고 예제 5의 출력 :
[tree]
├ tree\.
├ tree\..
├ tree\dirA\.
├ tree\dirA\..
├ tree\dirA\dirB\.
├ tree\dirA\dirB\..
├ tree\dirA\dirB\fileD
├ tree\dirA\fileB
├ tree\dirA\fileC
├ tree\fileA
물론 미인 대회에서이기는 것은 아니지만 재귀 반복기를 사용하면 키 와 값 의 선형 순서보다 더 많은 정보를 사용할 수 있음을 보여줍니다 . foreach
이러한 종류의 선형성을 표현할 수만 있어도 반복자 자체에 액세스하면 더 많은 정보를 얻을 수 있습니다.
메타 정보와 유사하게 트리를 순회하여 출력 순서를 지정하는 방법도 여러 가지가 있습니다. 이것은의 모드 이며RecursiveIteratorIterator
생성자로 설정할 수 있습니다.
다음 예제 에서는 필요하지 않은 RecursiveDirectoryIterator
점 항목 ( .
및 ..
) 을 제거 하도록에 지시 합니다. 그러나 재귀 모드는 하위 (하위 디렉터리 SELF_FIRST
의 파일 및 하위 디렉터리)보다 먼저 상위 요소 (하위 디렉터리)를 먼저 ( ) 가져 오도록 변경됩니다.
$dir = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::SELF_FIRST);
echo "[$path]\n";
foreach ($files as $file) {
$indent = str_repeat(' ', $files->getDepth());
echo $indent, " ├ $file\n";
}
이전 출력과 비교하면 출력에 제대로 나열된 하위 디렉토리 항목이 표시됩니다.
[tree]
├ tree\dirA
├ tree\dirA\dirB
├ tree\dirA\dirB\fileD
├ tree\dirA\fileB
├ tree\dirA\fileC
├ tree\fileA
따라서 재귀 모드는 디렉토리 예제의 경우 트리에서 brach 또는 leaf가 반환되는 대상과시기를 제어합니다.
LEAVES_ONLY
(기본값) : 디렉토리없이 파일 만 나열합니다.SELF_FIRST
(위) : 디렉토리와 그 안에있는 파일을 나열합니다.CHILD_FIRST
(예제없이) : 먼저 하위 디렉토리의 파일을 나열한 다음 디렉토리를 나열합니다.다른 두 가지 모드가있는 예제 5의 출력 :
LEAVES_ONLY CHILD_FIRST
[tree] [tree]
├ tree\dirA\dirB\fileD ├ tree\dirA\dirB\fileD
├ tree\dirA\fileB ├ tree\dirA\dirB
├ tree\dirA\fileC ├ tree\dirA\fileB
├ tree\fileA ├ tree\dirA\fileC
├ tree\dirA
├ tree\fileA
표준 순회와 비교할 때이 모든 것을 사용할 수 없습니다. 따라서 재귀 반복은 머리를 감싸 야 할 때 조금 더 복잡하지만 반복자처럼 작동하기 때문에 사용하기 쉽습니다 foreach
.
나는 이것들이 하나의 대답에 대한 충분한 예라고 생각합니다. 이 요점에서 멋진 아스키 트리를 표시하는 예제와 전체 소스 코드를 찾을 수 있습니다 : https://gist.github.com/3599532
스스로를 수행 만들기 기능
RecursiveTreeIterator
선으로 직장 선.
예제 5 는 사용 가능한 반복기의 상태에 대한 메타 정보가 있음을 보여줍니다. 그러나 이것은 반복 내 에서 의도적으로 입증되었습니다 foreach
. 실제 생활에서 이것은 자연스럽게 RecursiveIterator
.
더 좋은 예는 RecursiveTreeIterator
이며 들여 쓰기, 접두사 등을 처리합니다. 다음 코드 조각을 참조하십시오.
$dir = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS);
$lines = new RecursiveTreeIterator($dir);
$unicodeTreePrefix($lines);
echo "[$path]\n", implode("\n", iterator_to_array($lines));
이 RecursiveTreeIterator
라인으로 작업 라인에 의도, 출력은 꽤 똑바로 앞으로 하나 개의 작은 문제에있다 :
[tree]
├ tree\dirA
│ ├ tree\dirA\dirB
│ │ └ tree\dirA\dirB\fileD
│ ├ tree\dirA\fileB
│ └ tree\dirA\fileC
└ tree\fileA
와 함께 사용 RecursiveDirectoryIterator
하면 파일 이름뿐만 아니라 전체 경로 이름이 표시됩니다. 나머지는 좋아 보인다. 파일 이름은 SplFileInfo
. 대신 기본 이름으로 표시되어야합니다. 원하는 출력은 다음과 같습니다.
/// Solved ///
[tree]
├ dirA
│ ├ dirB
│ │ └ fileD
│ ├ fileB
│ └ fileC
└ fileA
RecursiveTreeIterator
대신에 사용할 수있는 데코레이터 클래스를 만듭니다 RecursiveDirectoryIterator
. SplFileInfo
경로 이름 대신 현재의 기본 이름을 제공해야합니다 . 최종 코드 조각은 다음과 같습니다.
$lines = new RecursiveTreeIterator(
new DiyRecursiveDecorator($dir)
);
$unicodeTreePrefix($lines);
echo "[$path]\n", implode("\n", iterator_to_array($lines));
다음을 포함 $unicodeTreePrefix
하는 이러한 단편 은 부록 : Do It Yourself : Make the RecursiveTreeIterator
Work Line by Line 의 요점의 일부입니다 . .
RecursiveIteratorIterator
이것은 다른 유형과 공통점이 있기 때문에 구체적인 구현 세부 사항을 여전히 생략 했지만 실제로 작동하는 방법에 대한 기술 정보를 제공했습니다. 내가 생각하는 예는 잘 차이를 보여 반복의 유형 입니다 둘 간의 주요한 차이가있다. 반복 유형을 구입하면 조금 다르게 동전을 만들지 모르지만 IMHO는 반복의 의미 유형이 쉽지 않습니다.
IteratorIterator
과 의 차이점은 무엇입니까RecursiveIteratorIterator
?
이 두 반복자의 차이점을 이해하려면 먼저 사용 된 명명 규칙과 "재귀"반복자가 의미하는 바에 대해 약간 이해해야합니다.
PHP 같은 비 "순환"이터레이터 가지고 ArrayIterator
와 FilesystemIterator
. 등으로 "재귀"반복자도있다 RecursiveArrayIterator
하고 RecursiveDirectoryIterator
. 후자는 드릴 다운 할 수있는 방법이 있지만 전자는 그렇지 않습니다.
이러한 반복기의 인스턴스가 자체적으로 반복되는 경우, 심지어 반복되는 경우에도 하위 디렉토리가있는 중첩 배열 또는 디렉토리를 반복하더라도 값은 "최상위"수준에서만 제공됩니다.
재귀 반복자는 구현 (를 통해 반복적 동작을 hasChildren()
, getChildren()
)하지 않지만 공격 을.
"recursible"반복자는, 그들이 가지고있는 재귀 반복자 생각하는 더 좋을 수도 기능을 반복적으로 단순히 그렇게하지 않습니다 이러한 클래스 중 하나의 인스턴스를 반복하는 반복 될 수 있습니다. 재귀 적 행동을 이용하려면 계속 읽으십시오.
이것은 RecursiveIteratorIterator
플레이에 오는 곳 입니다. 일반, 플랫, 루프에서 구조로 드릴 다운하는 방식으로 "재귀 가능"반복자를 호출하는 방법에 대한 지식을 가지고 있습니다. 재귀 적 동작을 실행합니다. 그것은 본질적으로 반복기의 각 값을 단계별로 실행하고, 반복 할 "자식"이 있는지 확인하고, 이러한 자식 컬렉션에 들어오고 나가는 작업을 수행합니다. 당신의 인스턴스를 스틱 RecursiveIteratorIterator
foreach 문에, 그리고 그것은 당신이하지 않도록 구조로 다이빙.
를 RecursiveIteratorIterator
사용하지 않았다면 재귀 동작을 이용하기 위해 자신의 재귀 루프를 작성하고 "재귀"반복자를 확인 hasChildren()
하고 getChildren()
.
에 대한 간략한 개요입니다.과 ( RecursiveIteratorIterator
와) 어떻게 다른 IteratorIterator
가요? 글쎄, 당신은 기본적으로 고양이와 나무의 차이점이 무엇입니까? 와 같은 종류의 질문을 하고 있습니다. 둘 다 동일한 백과 사전 (또는 반복기의 경우 매뉴얼)에 표시된다고해서 둘을 혼동해야하는 것은 아닙니다.
의 임무는 IteratorIterator
모든 Traversable
객체 를 가져와 Iterator
인터페이스를 만족하도록 감싸는 것 입니다. 이를위한 용도는 비 반복기 객체에 반복기 특정 동작을 적용 할 수 있다는 것입니다.
실제 예제를 제공하기 위해, DatePeriod
클래스는 Traversable
하지만 아닙니다 Iterator
. 따라서 값을 반복 할 수는 foreach()
있지만 일반적으로 반복기에서 수행하는 다른 작업 (예 : 필터링)은 수행 할 수 없습니다.
작업 : 다음 4주의 월요일, 수요일, 금요일을 반복합니다.
예, 이것은 루프 내에서 foreach
-ing DatePeriod
및 사용하여 사소한 것입니다 if()
. 그러나 그것은이 예제의 요점이 아닙니다!
$period = new DatePeriod(new DateTime, new DateInterval('P1D'), 28);
$dates = new CallbackFilterIterator($period, function ($date) {
return in_array($date->format('l'), array('Monday', 'Wednesday', 'Friday'));
});
foreach ($dates as $date) { … }
위의 스 니펫은 인터페이스 CallbackFilterIterator
를 구현하는 클래스의 인스턴스를 예상 하기 때문에 작동 하지 않습니다. 그러나 를 사용하면 그 요구 사항을 쉽게 충족시킬 수 있습니다 .Iterator
DatePeriod
Traversable
IteratorIterator
$period = new IteratorIterator(new DatePeriod(…));
보시다시피, 이것은 반복자 클래스 또는 재귀에 대한 반복과 관련 이 없으며 그 안에 IteratorIterator
와 사이의 차이가 RecursiveIteratorIterator
있습니다.
RecursiveIteraratorIterator
RecursiveIterator
( "재귀"반복자) 를 반복 하여 사용 가능한 재귀 동작을 이용합니다.
IteratorIterator
Iterator
반복자가 아닌 Traversable
객체에 동작을 적용하기위한 것 입니다.
IteratorIterator
에 대한 선형 주문 탐색의 표준 유형의 단지 Traversable
객체는? 그것없이 그대로 사용할 수있는 foreach
것? 그리고 더욱, a는 아니다 RecursiveIterator
항상Traversable
때문에뿐만 IteratorIterator
아니라 RecursiveIteratorIterator
항상 "적용을위한 Iterator
비 반복자는,에 이동 객체에 동작을" ? (이제 foreach
반복자 유형 인터페이스를 구현하는 컨테이너 객체에 반복자 객체를 통해 반복 유형을 적용 한다고 말하고 싶습니다. 그래서 이들은 항상 반복자-컨테이너 객체입니다. Traversable
)
IteratorIterator
포장에 대한 모든 인 클래스입니다 Traversable
의 객체 Iterator
. 더 이상은 없습니다 . 더 일반적으로 용어를 적용하는 것 같습니다.
Recursive
in은 RecursiveIterator
행동 을 암시 하기 때문에 그 이름은 오랫동안 나를 타락하게 만들었습니다 RecursibleIterator
. 반면에 더 적합한 이름은 .
와 함께 사용하면 iterator_to_array()
, RecursiveIteratorIterator
재귀 적으로 모든 값을 찾을 수있는 배열을 안내합니다. 원래 배열을 평평하게한다는 의미입니다.
IteratorIterator
원래 계층 구조를 유지합니다.
이 예는 차이점을 명확하게 보여줍니다.
$array = array(
'ford',
'model' => 'F150',
'color' => 'blue',
'options' => array('radio' => 'satellite')
);
$recursiveIterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
var_dump(iterator_to_array($recursiveIterator, true));
$iterator = new IteratorIterator(new ArrayIterator($array));
var_dump(iterator_to_array($iterator,true));
new IteratorIterator(new ArrayIterator($array))
에 해당 new ArrayIterator($array)
, 즉, 외부 IteratorIterator
아무것도하지 않고있다. 더욱이 출력의 평면화는 아무 관련이 없습니다. iterator_to_array
단지 반복기를 배열로 변환하는 것입니다. 평탄화는 RecursiveArrayIterator
내부 반복자를 걷는 방식의 속성입니다 .
RecursiveDirectoryIterator는 파일 이름뿐만 아니라 전체 경로 이름을 표시합니다. 나머지는 좋아 보인다. 파일 이름이 SplFileInfo에 의해 생성되기 때문입니다. 대신 기본 이름으로 표시되어야합니다. 원하는 출력은 다음과 같습니다.
$path =__DIR__;
$dir = new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS);
$files = new RecursiveIteratorIterator($dir,RecursiveIteratorIterator::SELF_FIRST);
while ($files->valid()) {
$file = $files->current();
$filename = $file->getFilename();
$deep = $files->getDepth();
$indent = str_repeat('│ ', $deep);
$files->next();
$valid = $files->valid();
if ($valid and ($files->getDepth() - 1 == $deep or $files->getDepth() == $deep)) {
echo $indent, "├ $filename\n";
} else {
echo $indent, "└ $filename\n";
}
}
산출:
tree
├ dirA
│ ├ dirB
│ │ └ fileD
│ ├ fileB
│ └ fileC
└ fileA