Bagaimana cara RecursiveIteratorIteratorkerjanya?
Manual PHP tidak banyak didokumentasikan atau dijelaskan. Apa perbedaan antara IteratorIteratordan RecursiveIteratorIterator?
Bagaimana cara RecursiveIteratorIteratorkerjanya?
Manual PHP tidak banyak didokumentasikan atau dijelaskan. Apa perbedaan antara IteratorIteratordan RecursiveIteratorIterator?
RecursiveIteratorIteratorkerjanya, apakah Anda sudah mengerti cara IteratorIteratorkerjanya? Maksud saya pada dasarnya sama, hanya antarmuka yang dikonsumsi oleh keduanya yang berbeda. Dan apakah Anda lebih tertarik pada beberapa contoh atau Anda ingin melihat perbedaan dari implementasi kode C yang mendasarinya?
IteratorIteratorpeta Iteratordan IteratorAggregatemenjadi Iterator, di mana REcusiveIteratorIteratordigunakan untuk melintasi recusivly aRecursiveIterator
Jawaban:
RecursiveIteratorIteratoradalah traversal pohonIterator pelaksana beton . Ini memungkinkan programmer untuk melintasi objek kontainer yang mengimplementasikan antarmuka, lihat Iterator di Wikipedia untuk prinsip umum, jenis, semantik, dan pola iterator.RecursiveIterator
Dalam perbedaan IteratorIteratoryang merupakan Iteratortraversal objek implementasi konkret dalam urutan linier (dan secara default menerima semua jenis Traversabledalam konstruktornya), RecursiveIteratorIteratorperulangan memungkinkan atas semua node dalam pohon objek yang diurutkan dan konstruktornya mengambil a RecursiveIterator.
Singkatnya: RecursiveIteratorIteratormemungkinkan Anda untuk melakukan loop di atas pohon, IteratorIteratormemungkinkan Anda untuk melakukan loop di atas daftar. Saya tunjukkan dengan beberapa contoh kode di bawah ini segera.
Secara teknis, ini bekerja dengan mendobrak linieritas dengan melintasi semua turunan node (jika ada). Hal ini dimungkinkan karena menurut definisi semua anak dari sebuah node kembali a RecursiveIterator. Tingkat atas Iteratorkemudian secara internal menumpuk RecursiveIterators yang berbeda berdasarkan kedalamannya dan menyimpan penunjuk ke sub aktif saat ini Iteratoruntuk traversal.
Ini memungkinkan untuk mengunjungi semua simpul pohon.
Prinsip dasarnya sama dengan IteratorIterator: Antarmuka menentukan jenis iterasi dan kelas iterator dasar adalah implementasi dari semantik ini. Bandingkan dengan contoh di bawah ini, untuk perulangan linier dengan foreachAnda biasanya tidak terlalu memikirkan detail implementasi kecuali Anda perlu mendefinisikan yang baru Iterator(misalnya ketika beberapa jenis konkret itu sendiri tidak diimplementasikan Traversable).
Untuk traversal rekursif - kecuali jika Anda tidak menggunakan Traversaliterasi traversal yang ditentukan sebelumnya yang sudah memiliki iterasi traversal rekursif - Anda biasanya perlu membuat instance RecursiveIteratorIteratoriterasi yang ada atau bahkan menulis iterasi traversal rekursif yang TraversableAnda miliki untuk memiliki jenis iterasi traversal ini foreach.
Tip: Anda mungkin tidak menerapkan yang satu atau yang lain milik Anda, jadi ini mungkin sesuatu yang layak dilakukan untuk pengalaman praktis Anda tentang perbedaan yang mereka miliki. Anda menemukan saran DIY di akhir jawaban.
Perbedaan teknis singkatnya:
IteratorIteratormengambil apapun Traversableuntuk linier traversal, RecursiveIteratorIteratormembutuhkan lebih spesifik RecursiveIteratoruntuk melakukan loop di atas pohon.IteratorIteratormengekspos utamanya Iteratormelalui getInnerIerator(), RecursiveIteratorIteratormenyediakan sub- Iteratorhanya aktif saat ini melalui metode itu.IteratorIteratorsama sekali tidak menyadari apa pun seperti orang tua atau anak, RecursiveIteratorIteratortahu bagaimana cara mendapatkan dan melintasi anak juga.IteratorIteratortidak membutuhkan tumpukan iterator, RecursiveIteratorIteratormemiliki tumpukan seperti itu dan mengetahui sub-iterator yang aktif.IteratorIteratormemiliki urutannya karena linieritas dan tidak ada pilihan, RecursiveIteratorIteratormemiliki pilihan untuk traversal lebih lanjut dan perlu memutuskan per setiap node (diputuskan melalui mode perRecursiveIteratorIterator ).RecursiveIteratorIteratormemiliki lebih banyak metode daripada IteratorIterator.Untuk meringkas: RecursiveIteratoradalah jenis konkret dari iterasi (perulangan di atas pohon) yang bekerja pada iteratornya sendiri, yaitu RecursiveIterator. Itu adalah prinsip dasar yang sama seperti dengan IteratorIerator, tetapi jenis iterasinya berbeda (urutan linier).
Idealnya, Anda juga dapat membuat set sendiri. Satu-satunya hal yang perlu adalah bahwa iterator Anda mengimplementasikan Traversableyang mungkin dilakukan melalui Iteratoratau IteratorAggregate. Kemudian Anda bisa menggunakannya dengan foreach. Misalnya beberapa jenis objek iterasi rekursif traversal terner pohon bersama dengan antarmuka iterasi yang sesuai untuk objek kontainer.
Mari kita ulas dengan beberapa contoh kehidupan nyata yang tidak terlalu abstrak. Antara antarmuka, iterator beton, objek kontainer, dan semantik iterasi, ini mungkin bukan ide yang buruk.
Ambil daftar direktori sebagai contoh. Pertimbangkan Anda telah mendapatkan file dan pohon direktori berikut pada disk:
Sementara iterator dengan urutan linier hanya melintasi folder dan file tingkat atas (daftar direktori tunggal), iterator rekursif juga melintasi subfolder dan mencantumkan semua folder dan file (daftar direktori dengan daftar subdirektorinya):
Non-Recursive Recursive
============= =========
[tree] [tree]
├ dirA ├ dirA
└ fileA │ ├ dirB
│ │ └ fileD
│ ├ fileB
│ └ fileC
└ fileA
Anda dapat dengan mudah membandingkan ini dengan IteratorIteratoryang tidak melakukan rekursi untuk melintasi pohon direktori. Dan RecursiveIteratorIteratoryang dapat melintasi pohon seperti yang ditunjukkan daftar Rekursif.
Pada awalnya contoh yang sangat mendasar dengan DirectoryIteratoryang mengimplementasikan Traversableyang memungkinkan foreachuntuk mengulanginya :
$path = 'tree';
$dir = new DirectoryIterator($path);
echo "[$path]\n";
foreach ($dir as $file) {
echo " ├ $file\n";
}
Keluaran contoh untuk struktur direktori di atas adalah:
[tree]
├ .
├ ..
├ dirA
├ fileA
Seperti yang Anda lihat, ini belum menggunakan IteratorIteratoratau RecursiveIteratorIterator. Sebaliknya itu hanya menggunakan foreachyang beroperasi pada Traversableantarmuka.
Karena foreachsecara default hanya mengetahui jenis iterasi bernama urutan linier, kita mungkin ingin menentukan jenis iterasi secara eksplisit. Sekilas mungkin tampak terlalu bertele-tele, tetapi untuk tujuan demonstrasi (dan untuk membuat perbedaan dengan RecursiveIteratorIteratorlebih terlihat nanti), mari kita tentukan tipe linier dari iterasi secara eksplisit menentukan IteratorIteratorjenis iterasi untuk daftar direktori:
$files = new IteratorIterator($dir);
echo "[$path]\n";
foreach ($files as $file) {
echo " ├ $file\n";
}
Contoh ini hampir identik dengan yang pertama, perbedaannya $filesadalah sekarang menjadi IteratorIteratorjenis iterasi untuk Traversable $dir:
$files = new IteratorIterator($dir);
Seperti biasa tindakan iterasi dilakukan oleh foreach:
foreach ($files as $file) {
Outputnya persis sama. Jadi apa bedanya? Yang berbeda adalah objek yang digunakan di dalam foreach. Dalam contoh pertama ini adalah a, DirectoryIteratordalam contoh kedua itu adalah IteratorIterator. Ini menunjukkan fleksibilitas yang dimiliki iterator: Anda dapat menggantinya satu sama lain, kode di dalamnya foreachterus berfungsi seperti yang diharapkan.
Mari mulai mendapatkan seluruh daftar, termasuk subdirektori.
Karena sekarang kita telah menentukan jenis iterasi, mari pertimbangkan untuk mengubahnya ke jenis iterasi lain.
Kami tahu kami perlu melintasi seluruh pohon sekarang, tidak hanya tingkat pertama. Untuk memiliki pekerjaan dengan sederhana foreachkita membutuhkan berbagai jenis iterator: RecursiveIteratorIterator. Dan yang satu itu hanya dapat melakukan iterasi pada objek kontainer yang memiliki RecursiveIteratorantarmuka .
Antarmuka adalah kontrak. Setiap kelas yang mengimplementasikannya dapat digunakan bersama dengan RecursiveIteratorIterator. Contoh dari kelas tersebut adalah the RecursiveDirectoryIterator, yang merupakan varian rekursif dari DirectoryIterator.
Mari kita lihat contoh kode pertama sebelum menulis kalimat lain dengan kata-I:
$dir = new RecursiveDirectoryIterator($path);
echo "[$path]\n";
foreach ($dir as $file) {
echo " ├ $file\n";
}
Contoh ketiga ini hampir identik dengan yang pertama, namun menghasilkan beberapa keluaran yang berbeda:
[tree]
├ tree\.
├ tree\..
├ tree\dirA
├ tree\fileA
Oke, tidak jauh berbeda, nama file sekarang berisi nama jalur di depan, tetapi sisanya terlihat serupa juga.
Seperti yang ditunjukkan contoh, bahkan objek direktori sudah mengimplementasikan RecursiveIteratorantarmuka, ini belum cukup untuk foreachmelintasi seluruh pohon direktori. Di sinilah RecursiveIteratorIteratorberaksi. Contoh 4 menunjukkan bagaimana:
$files = new RecursiveIteratorIterator($dir);
echo "[$path]\n";
foreach ($files as $file) {
echo " ├ $file\n";
}
Menggunakan RecursiveIteratorIteratoralih - alih hanya $dirobjek sebelumnya akan membuat foreachmelintasi semua file dan direktori secara rekursif. Ini kemudian mencantumkan semua file, karena jenis iterasi objek telah ditentukan sekarang:
[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
Ini seharusnya sudah menunjukkan perbedaan antara traversal datar dan pohon. The RecursiveIteratorIteratormampu melintasi setiap struktur seperti pohon sebagai daftar elemen. Karena terdapat lebih banyak informasi (seperti level yang dilakukan iterasi saat ini), dimungkinkan untuk mengakses objek iterator sambil mengulanginya dan misalnya mengindentasi output:
echo "[$path]\n";
foreach ($files as $file) {
$indent = str_repeat(' ', $files->getDepth());
echo $indent, " ├ $file\n";
}
Dan keluaran dari Contoh 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
Tentu ini tidak memenangkan kontes kecantikan, tetapi ini menunjukkan bahwa dengan iterator rekursif ada lebih banyak informasi yang tersedia daripada hanya urutan linier kunci dan nilai . Bahkan foreachhanya dapat mengekspresikan linieritas semacam ini, mengakses iterator itu sendiri memungkinkan untuk memperoleh lebih banyak informasi.
Mirip dengan meta-informasi, ada juga cara berbeda yang memungkinkan bagaimana melintasi pohon dan karenanya mengurutkan keluaran. Ini adalah mode dariRecursiveIteratorIterator dan dapat diatur dengan konstruktor.
Contoh selanjutnya akan memberitahu RecursiveDirectoryIteratoruntuk menghapus entri titik ( .dan ..) karena kita tidak membutuhkannya. Tetapi juga mode rekursi akan diubah untuk mengambil elemen induk (subdirektori) terlebih dahulu ( SELF_FIRST) sebelum anak-anak (file dan sub-subdirektori di subdirektori):
$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";
}
Output sekarang menunjukkan entri subdirektori terdaftar dengan benar, jika Anda membandingkan dengan output sebelumnya yang tidak ada:
[tree]
├ tree\dirA
├ tree\dirA\dirB
├ tree\dirA\dirB\fileD
├ tree\dirA\fileB
├ tree\dirA\fileC
├ tree\fileA
Karena itu, mode rekursi mengontrol apa dan kapan brach atau leaf di pohon dikembalikan, untuk contoh direktori:
LEAVES_ONLY (default): Hanya daftar file, tidak ada direktori.SELF_FIRST (atas): Daftar direktori dan kemudian file-file di sana.CHILD_FIRST (tanpa contoh): Buat daftar file di subdirektori terlebih dahulu, lalu direktori.Output dari Contoh 5 dengan dua mode lainnya:
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
Jika Anda membandingkannya dengan traversal standar, semua hal ini tidak tersedia. Oleh karena itu, iterasi rekursif sedikit lebih kompleks ketika Anda perlu membungkusnya, namun mudah digunakan karena berperilaku seperti iterator, Anda memasukkannya ke dalam foreachdan selesai.
Saya pikir ini adalah contoh yang cukup untuk satu jawaban. Anda dapat menemukan kode sumber lengkap serta contoh untuk menampilkan ascii-tree yang bagus di intinya: https://gist.github.com/3599532
Lakukan Sendiri: Buat
RecursiveTreeIteratorPekerjaan Baris demi Baris.
Contoh 5 menunjukkan bahwa ada meta-informasi tentang status iterator yang tersedia. Namun, ini sengaja ditunjukkan dalam yang foreachiterasi. Dalam kehidupan nyata, ini secara alami termasuk di dalam RecursiveIterator.
Contoh yang lebih baik adalah RecursiveTreeIterator, ini menangani indentasi, awalan, dan sebagainya. Lihat fragmen kode berikut:
$dir = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS);
$lines = new RecursiveTreeIterator($dir);
$unicodeTreePrefix($lines);
echo "[$path]\n", implode("\n", iterator_to_array($lines));
Ini RecursiveTreeIteratordimaksudkan untuk bekerja baris demi baris, hasilnya cukup lurus ke depan dengan satu masalah kecil:
[tree]
├ tree\dirA
│ ├ tree\dirA\dirB
│ │ └ tree\dirA\dirB\fileD
│ ├ tree\dirA\fileB
│ └ tree\dirA\fileC
└ tree\fileA
Saat digunakan dalam kombinasi dengan a, RecursiveDirectoryIteratorini akan menampilkan seluruh nama jalur dan bukan hanya nama file. Sisanya terlihat bagus. Ini karena nama file dibuat oleh SplFileInfo. Itu harus ditampilkan sebagai nama dasar sebagai gantinya. Output yang diinginkan adalah sebagai berikut:
/// Solved ///
[tree]
├ dirA
│ ├ dirB
│ │ └ fileD
│ ├ fileB
│ └ fileC
└ fileA
Buat kelas dekorator yang bisa digunakan dengan RecursiveTreeIteratorsebagai pengganti RecursiveDirectoryIterator. Ini harus memberikan nama dasar saat ini, SplFileInfobukan nama jalur. Fragmen kode terakhir akan terlihat seperti ini:
$lines = new RecursiveTreeIterator(
new DiyRecursiveDecorator($dir)
);
$unicodeTreePrefix($lines);
echo "[$path]\n", implode("\n", iterator_to_array($lines));
Fragmen-fragmen ini termasuk $unicodeTreePrefixmerupakan bagian dari inti dalam Lampiran: Lakukan Sendiri: Buat RecursiveTreeIteratorPekerjaan Baris demi Baris. .
RecursiveIteratorIteratorkarena ini sama dengan jenis lain tetapi saya memberikan beberapa info teknis tentang cara kerjanya sebenarnya. Contoh yang menurut saya menunjukkan perbedaannya dengan baik: jenis iterasi adalah perbedaan utama di antara keduanya. Tidak tahu jika Anda membeli jenis iterasi yang Anda koin itu sedikit berbeda tetapi IMHO tidak mudah dengan jenis iterasi semantik yang dimiliki.
Apa perbedaan dari
IteratorIteratordanRecursiveIteratorIterator?
Untuk memahami perbedaan antara kedua iterator ini, pertama-tama kita harus memahami sedikit tentang konvensi penamaan yang digunakan dan apa yang kami maksud dengan iterator "rekursif".
PHP memiliki iterator non- "rekursif", seperti ArrayIteratordan FilesystemIterator. Ada juga iterator "rekursif" seperti RecursiveArrayIteratordan RecursiveDirectoryIterator. Yang terakhir memiliki metode yang memungkinkan mereka untuk dibor, yang pertama tidak.
Ketika instance dari iterator ini di-loop sendiri, bahkan yang rekursif, nilainya hanya datang dari level "top" meskipun melakukan looping pada array atau direktori bersarang dengan sub-direktori.
Iterator rekursif mengimplementasikan perilaku rekursif (via hasChildren(), getChildren()) tetapi tidak mengeksploitasinya .
Mungkin lebih baik untuk menganggap iterator rekursif sebagai iterator "rekursif", mereka memiliki kemampuan untuk diiterasi secara rekursif tetapi hanya melakukan iterasi pada sebuah instance dari salah satu kelas ini tidak akan melakukannya. Untuk memanfaatkan perilaku rekursif, teruslah membaca.
Di sinilah RecursiveIteratorIteratormasuk untuk bermain. Ia memiliki pengetahuan tentang bagaimana memanggil iterator yang "berulang" sedemikian rupa untuk menelusuri ke dalam struktur dalam loop normal, datar. Ini menempatkan perilaku rekursif ke dalam tindakan. Ini pada dasarnya melakukan pekerjaan untuk melangkahi setiap nilai dalam iterator, mencari untuk melihat apakah ada "anak-anak" untuk muncul kembali atau tidak, dan masuk dan keluar dari koleksi anak-anak itu. Anda memasukkan contoh RecursiveIteratorIteratorke depan, dan itu menyelam ke dalam struktur sehingga Anda tidak perlu melakukannya.
Jika RecursiveIteratorIteratortidak digunakan, Anda harus menulis loop rekursif Anda sendiri untuk mengeksploitasi perilaku rekursif, memeriksa iterator "rekursif" hasChildren()dan menggunakan getChildren().
Nah itulah gambaran singkat tentang RecursiveIteratorIterator, apa bedanya dengan IteratorIterator? Nah, pada dasarnya Anda menanyakan pertanyaan yang sama seperti Apa perbedaan antara anak kucing dan pohon? Hanya karena keduanya muncul dalam ensiklopedia yang sama (atau manual, untuk iterator) tidak berarti Anda harus bingung di antara keduanya.
Tugasnya IteratorIteratoradalah mengambil Traversableobjek apa pun , dan membungkusnya sedemikian rupa sehingga memenuhi Iteratorantarmuka. Kegunaannya adalah untuk kemudian dapat menerapkan perilaku khusus iterator pada objek non-iterator.
Untuk memberikan contoh praktis, DatePeriodkelas tersebut Traversablebukan Iterator. Dengan demikian, kita dapat mengulang nilainya dengan foreach()tetapi tidak dapat melakukan hal-hal lain yang biasanya kita lakukan dengan iterator, seperti pemfilteran.
TUGAS : Ulangi hari Senin, Rabu, dan Jumat dalam empat minggu berikutnya.
Ya, ini sepele dengan- foreachmelewati DatePerioddan menggunakan if()dalam loop; tapi bukan itu inti dari contoh ini!
$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) { … }
Cuplikan di atas tidak akan berfungsi karena CallbackFilterIteratormengharapkan instance dari kelas yang mengimplementasikan Iteratorantarmuka, DatePeriodpadahal tidak. Namun, karena itu Traversablekami dapat dengan mudah memenuhi kebutuhan itu dengan menggunakan IteratorIterator.
$period = new IteratorIterator(new DatePeriod(…));
Seperti yang Anda lihat, ini tidak ada hubungannya sama sekali dengan iterasi kelas iterator atau rekursi, dan di situlah letak perbedaan antara IteratorIteratordan RecursiveIteratorIterator.
RecursiveIteraratorIteratoradalah untuk melakukan iterasi RecursiveIterator(iterator "berulang"), mengeksploitasi perilaku rekursif yang tersedia.
IteratorIteratoradalah untuk menerapkan Iteratorperilaku ke objek non-iterator Traversable.
IteratorIteratorhanya tipe standar dari traversal tatanan linier untuk Traversableobjek? Apa yang bisa digunakan tanpa itu foreachapa adanya? Dan lebih jauh lagi, bukankah RecursiveIterator selalu a Traversabledan karena itu tidak hanya IteratorIteratortetapi juga RecursiveIteratorIteratorselalu "untuk menerapkan Iteratorperilaku ke non-iterator, objek Traversable" ? (Sekarang saya akan mengatakan foreachmenerapkan tipe iterasi melalui objek iterator pada objek kontainer yang mengimplementasikan antarmuka tipe iterator jadi ini adalah objek-kontainer-iterator, selalu Traversable)
IteratorIteratoradalah kelas yang semuanya tentang membungkus Traversableobjek dalam file Iterator. Tidak lebih . Anda tampaknya menerapkan istilah tersebut secara lebih umum.
Recursivein RecursiveIteratormenyiratkan perilaku, sedangkan nama yang lebih cocok adalah yang menggambarkan kemampuan, seperti RecursibleIterator.
Saat digunakan dengan iterator_to_array(), RecursiveIteratorIteratorakan secara rekursif menjalankan array untuk menemukan semua nilai. Artinya itu akan meratakan array aslinya.
IteratorIterator akan mempertahankan struktur hierarki asli.
Contoh ini akan menunjukkan dengan jelas perbedaannya:
$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))setara dengan new ArrayIterator($array), yaitu, bagian luar IteratorIteratortidak melakukan apa pun. Selain itu, perataan output tidak ada hubungannya dengan iterator_to_array- itu hanya mengubah iterator menjadi array. Perataan adalah sifat dari cara RecursiveArrayIteratorberjalan iterator bagian dalamnya.
RecursiveDirectoryIterator menampilkan seluruh nama jalur dan bukan hanya nama file. Sisanya terlihat bagus. Ini karena nama file dibuat oleh SplFileInfo. Itu harus ditampilkan sebagai nama dasar sebagai gantinya. Output yang diinginkan adalah sebagai berikut:
$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";
}
}
keluaran:
tree
├ dirA
│ ├ dirB
│ │ └ fileD
│ ├ fileB
│ └ fileC
└ fileA