Nasıl RecursiveIteratorIterator
çalışır?
PHP kılavuzunda çok fazla belgelenmiş veya açıklanmış hiçbir şey yoktur. Arasındaki fark nedir IteratorIterator
ve RecursiveIteratorIterator
?
Nasıl RecursiveIteratorIterator
çalışır?
PHP kılavuzunda çok fazla belgelenmiş veya açıklanmış hiçbir şey yoktur. Arasındaki fark nedir IteratorIterator
ve RecursiveIteratorIterator
?
RecursiveIteratorIterator
çalıştığını sorarsanız, nasıl çalıştığını zaten anladınız IteratorIterator
mı? Demek istediğim, temelde aynı, sadece ikisi tarafından tüketilen arayüz farklı. Ve bazı örneklerle mi daha çok ilgileniyorsunuz yoksa temeldeki C kodu uygulamasının farkını mı görmek istiyorsunuz?
IteratorIterator
haritalar Iterator
ve IteratorAggregate
bir Iterator
, REcusiveIteratorIterator
tekrarlanabilir şekilde geçmek için kullanılan birRecursiveIterator
Yanıtlar:
RecursiveIteratorIterator
somut bir Iterator
uygulama ağacı geçişidir . Bir programcının RecursiveIterator
arayüzü uygulayan bir konteyner nesnesini geçmesini sağlar, yineleyicilerin genel ilkeleri, türleri, anlambilim ve örüntüleri için Wikipedia'daki Yineleyiciye bakın.
Farkı ise hiç IteratorIterator
hangi bir betondur Iterator
lineer sırayla (ve varsayılan olarak her türlü kabul uygulayan nesne geçişi Traversable
onun kurucu), RecursiveIteratorIterator
bir bütün düğümleri üzerinde döngü verir sipariş ağacın nesnelerin ve yapıcı bir sürer RecursiveIterator
.
Kısaca: RecursiveIteratorIterator
bir ağaç IteratorIterator
üzerinde döngü yapmanıza, bir liste üzerinden döngü yapmanıza olanak tanır. Bunu yakında bazı kod örnekleriyle göstereceğim.
Teknik olarak bu, bir düğümün tüm çocuklarını (varsa) geçerek doğrusallığın dışına çıkarak çalışır. Bu mümkündür, çünkü tanım gereği bir düğümün tüm çocukları yine a'dır RecursiveIterator
. Üst seviye Iterator
daha sonra farklı s'leri RecursiveIterator
derinliklerine göre dahili olarak istifler ve Iterator
geçiş için geçerli aktif alt seviyeye bir işaretçi tutar .
Bu, bir ağacın tüm düğümlerini ziyaret etmeyi sağlar.
Temel ilkeler şununla aynıdır IteratorIterator
: Bir arabirim yinelemenin türünü belirtir ve temel yineleme sınıfı bu anlambilimin uygulamasıdır. Aşağıdaki örneklerle karşılaştırın, doğrusal döngü için foreach
sizinle normalde yeni bir tanımlamanız gerekmedikçe uygulama ayrıntılarını fazla düşünmeyin Iterator
(örneğin, somut bir türün kendisi uygulanmadığında Traversable
).
Özyinelemeli geçişi için - bir kullanmayan sürece öncesi tanımlı Traversal
zaten özyinelemeli geçişi yineleme sahip olduğunu - normalde ihtiyaç mevcut örneğini RecursiveIteratorIterator
iterasyon hatta yazma bir özyinelemeli geçişi yineleme bir olduğunu Traversable
kastetmek iterasyon ile bu tür olması için kendi foreach
.
İpucu: Muhtemelen birini ya da diğerini kendiniz uygulamadınız, bu yüzden bu, aralarındaki farklılıklara ilişkin pratik deneyiminiz için yapmaya değer bir şey olabilir. Cevabın sonunda bir DIY önerisi buluyorsunuz.
Kısaca teknik farklılıklar:
IteratorIterator
herhangi birini alırken , bir ağaç üzerinde döngü için daha spesifik bir ihtiyaç vardır .Traversable
RecursiveIteratorIterator
RecursiveIterator
IteratorIterator
ana ortaya Iterator
ile getInnerIerator()
, RecursiveIteratorIterator
mevcut aktif alt sağlar Iterator
ancak bu yöntem ile.IteratorIterator
tamamen ebeveyn veya çocuk gibi her şeyin farkında değildir, RecursiveIteratorIterator
aynı zamanda almak ve travers çocuklar bilir.IteratorIterator
bir yineleyici yığınına ihtiyaç duymaz RecursiveIteratorIterator
, böyle bir yığını vardır ve aktif alt yineleyiciyi bilir.IteratorIterator
lineer ve seçim nedeniyle siparişini sahiptir RecursiveIteratorIterator
ileri kastetmek ve her düğüm başına karar vermek ihtiyaçları için seçeneği vardır (aracılığıyla karar mod başınaRecursiveIteratorIterator
).RecursiveIteratorIterator
daha fazla yöntemi var IteratorIterator
.Özetlemek gerekirse: RecursiveIterator
kendi yineleyicileri üzerinde çalışan somut bir yineleme türüdür (bir ağaç üzerinde döngüdür) RecursiveIterator
. Bu, temelde yatan ilke ile aynıdır IteratorIerator
, ancak yineleme türü farklıdır (doğrusal sıra).
İdeal olarak kendi setinizi de oluşturabilirsiniz. Gerekli olan tek şey, yineleyicinizin veya Traversable
aracılığıyla mümkün olanı gerçekleştirmesidir . O zaman kullanabilirsinizIterator
IteratorAggregate
foreach
. Örneğin, konteyner nesnesi (leri) için uygun yineleme arabirimi ile birlikte bir tür üçlü ağaç çapraz yinelemeli yineleme nesnesi.
O kadar soyut olmayan bazı gerçek hayattan örneklerle gözden geçirelim. Arayüzler, somut yineleyiciler, kapsayıcı nesneler ve yineleme semantiği arasında bu belki de o kadar da kötü bir fikir değil.
Örnek olarak bir dizin listesi alın. Diskte aşağıdaki dosya ve dizin ağacına sahip olduğunuzu düşünün:
Doğrusal sıraya sahip bir yineleyici, üst düzey klasör ve dosyalar üzerinde gezinirken (tek bir dizin listesi), yinelemeli yineleyici, alt klasörler arasında da gezinir ve tüm klasörleri ve dosyaları listeler (alt dizinlerinin listelerini içeren bir dizin listesi):
Non-Recursive Recursive
============= =========
[tree] [tree]
├ dirA ├ dirA
└ fileA │ ├ dirB
│ │ └ fileD
│ ├ fileB
│ └ fileC
└ fileA
Bunu IteratorIterator
, dizin ağacında gezinmek için hiçbir özyineleme yapmayanla kolayca karşılaştırabilirsiniz . VeRecursiveIteratorIterator
Özyinelemeli listenin gösterdiği gibi ağaçtan geçebilir.
Bir ilk çok temel bir örnek de DirectoryIterator
bunu uygulayan Traversable
verir foreach
için yineleme üzerine:
$path = 'tree';
$dir = new DirectoryIterator($path);
echo "[$path]\n";
foreach ($dir as $file) {
echo " ├ $file\n";
}
Yukarıdaki dizin yapısı için örnek çıktı:
[tree]
├ .
├ ..
├ dirA
├ fileA
Gördüğünüz gibi bu henüz IteratorIterator
veya kullanmıyor RecursiveIteratorIterator
. Bunun yerine sadece sadece kullanılarak foreach
bu konuda faaliyetTraversable
arayüzde .
Gibi foreach
yalnızca doğrusal düzen adlı yineleme türünü bilen varsayılan olarak, biz açıkça yineleme türünü belirtmek isteyebilirsiniz. İlk bakışta çok ayrıntılı görünebilir, ancak gösterim amacıyla (ve RecursiveIteratorIterator
daha sonra daha görünür IteratorIterator
olması için), dizin listesi için yineleme türünü açıkça belirterek doğrusal yineleme türünü belirleyelim :
$files = new IteratorIterator($dir);
echo "[$path]\n";
foreach ($files as $file) {
echo " ├ $file\n";
}
Bu örnek, ilkiyle neredeyse aynıdır , aradaki fark, $files
şu anda aşağıdakiler için bir IteratorIterator
tür yineleme olmasıdır Traversable
$dir
:
$files = new IteratorIterator($dir);
Her zamanki gibi, yineleme eylemi aşağıdakiler tarafından gerçekleştirilir foreach
:
foreach ($files as $file) {
Çıktı tamamen aynı. Öyleyse farklı olan nedir? İçinde kullanılan nesne farklıdır foreach
. İlk örnekte bu, DirectoryIterator
ikinci örnekte bir IteratorIterator
. Bu, yineleyicilerin sahip olduğu esnekliği gösterir: Bunları birbirleriyle değiştirebilirsiniz, içindeki kodforeach
beklendiği gibi çalışmaya devam eder.
Alt dizinler dahil tüm listeyi almaya başlayalım.
Şimdi yineleme türünü belirttiğimiz gibi, onu başka bir yineleme türüne değiştirmeyi düşünelim.
Şimdi sadece ilk seviyeyi değil, tüm ağacı geçmemiz gerektiğini biliyoruz. Bir basit olan bu işi sahip olmak foreach
biz Yineleyici farklı türde bir gerekir: RecursiveIteratorIterator
. Ve bu, yalnızca arayüze sahip konteyner nesneleri üzerinde yineleme yapabilir.RecursiveIterator
.
Arayüz bir sözleşmedir. Bunu uygulayan herhangi bir sınıf RecursiveIteratorIterator
,. Böyle bir sınıfa örnek, ' RecursiveDirectoryIterator
nin özyinelemeli varyantı gibi bir şeydir.DirectoryIterator
.
I-word ile başka bir cümle yazmadan önce ilk kod örneğini görelim:
$dir = new RecursiveDirectoryIterator($path);
echo "[$path]\n";
foreach ($dir as $file) {
echo " ├ $file\n";
}
Bu üçüncü örnek ilkiyle neredeyse aynıdır, ancak bazı farklı çıktılar yaratır:
[tree]
├ tree\.
├ tree\..
├ tree\dirA
├ tree\fileA
Tamam, o kadar da farklı değil, dosya adı artık öndeki yol adını içeriyor, ancak geri kalanı da benzer görünüyor.
Örnekte gösterildiği gibi, dizin nesnesi zaten RecursiveIterator
arabirimi taklit etse bile , bu henüz foreach
tüm dizin ağacını çapraz geçiş yapmak için yeterli değildir . İşte burada RecursiveIteratorIterator
devreye giriyor. Örnek 4 şunları göstermektedir:
$files = new RecursiveIteratorIterator($dir);
echo "[$path]\n";
foreach ($files as $file) {
echo " ├ $file\n";
}
Kullanılması RecursiveIteratorIterator
yerine önceki bir $dir
nesne yapacak foreach
bir özyinelemeli şekilde tüm dosyaları ve dizinleri üzerinde hareket etmesi. Bu, daha sonra nesne yineleme türü şimdi belirtildiğinden tüm dosyaları listeler:
[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
Bu, düz ve ağaç geçişi arasındaki farkı zaten göstermelidir. RecursiveIteratorIterator
Elemanlarının bir listesi olarak herhangi bir ağaç benzeri bir yapı çapraz edebilmektedir. Daha fazla bilgi olduğu için (yinelemenin o anda gerçekleştiği düzey gibi), üzerinde yineleyerek yineleyici nesneye erişmek ve örneğin çıktıyı girintilemek mümkündür:
echo "[$path]\n";
foreach ($files as $file) {
$indent = str_repeat(' ', $files->getDepth());
echo $indent, " ├ $file\n";
}
Ve Örnek 5'in çıktısı :
[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
Elbette bu bir güzellik yarışmasını kazanmaz, ancak yinelemeli yinelemeyle, anahtar ve değerin doğrusal sırasından daha fazla bilgi bulunduğunu gösterir . Hatta foreach
sadece bu tür bir doğrusallığı ifade edebilir, yineleyicinin kendisine erişmek daha fazla bilgi elde etmeyi sağlar.
Meta bilgiye benzer şekilde, ağacın üzerinden geçmenin ve dolayısıyla çıktıyı sipariş etmenin farklı yolları da vardır. Bu Mod arasındaRecursiveIteratorIterator
ve yapıcı ile ayarlanabilir.
Bir sonraki örnek, ihtiyacımız olmadığı RecursiveDirectoryIterator
için nokta girişlerini ( .
ve ..
) kaldırmasını söyleyecektir . Ancak özyineleme modu, alt öğe (alt dizindeki SELF_FIRST
dosyalar ve alt dizinler) önce ( ) üst öğeyi (alt dizin) alacak şekilde değiştirilecektir :
$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";
}
Çıktı, artık orada olmayanlar önceki çıktıyla karşılaştırırsanız, alt dizin girişlerinin düzgün bir şekilde listelendiğini gösterir:
[tree]
├ tree\dirA
├ tree\dirA\dirB
├ tree\dirA\dirB\fileD
├ tree\dirA\fileB
├ tree\dirA\fileC
├ tree\fileA
Bu nedenle özyineleme modu, dizin örneği için ağaçtaki bir köşeli ayraç veya yaprağın ne ve ne zaman döndürüleceğini kontrol eder:
LEAVES_ONLY
(varsayılan): Yalnızca dosyaları listele, dizin yok.SELF_FIRST
(yukarıda): Dizini ve ardından içindeki dosyaları listeleyin.CHILD_FIRST
(örneksiz): Önce alt dizindeki dosyaları, ardından dizini listeleyin.Örnek 5'in diğer iki modla çıktısı :
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
Bunu standart geçişle karşılaştırdığınızda, tüm bunlar mevcut değildir. Bu nedenle özyinelemeli yineleme, kafanızı etrafına sarmanız gerektiğinde biraz daha karmaşıktır, ancak bir yineleyici gibi davrandığı için kullanımı kolaydır,foreach
ve bitirdiniz.
Sanırım bunlar bir cevap için yeterli örnek. Tam kaynak kodunu ve güzel görünümlü ascii ağaçlarını gösteren bir örneği bu özette bulabilirsiniz: https://gist.github.com/3599532
Kendin Yap :
RecursiveTreeIterator
İş Satırını Satır Satır Yap .
Örnek 5 , yineleyicinin durumu hakkında meta bilgi mevcut olduğunu gösterdi. Bununla birlikte, bu bilinçli gösterilmiştir içindeforeach
yineleme. Gerçek hayatta bu, doğal olarak RecursiveIterator
.
Daha iyi bir örnek, RecursiveTreeIterator
girinti, önek vb. İle ilgilenir. Aşağıdaki kod parçasına bakın:
$dir = new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS);
$lines = new RecursiveTreeIterator($dir);
$unicodeTreePrefix($lines);
echo "[$path]\n", implode("\n", iterator_to_array($lines));
RecursiveTreeIterator
Çizgi ile iş hattına amaçlanmaktadır çıkış oldukça yalındır bir küçük problem ile geçerli:
[tree]
├ tree\dirA
│ ├ tree\dirA\dirB
│ │ └ tree\dirA\dirB\fileD
│ ├ tree\dirA\fileB
│ └ tree\dirA\fileC
└ tree\fileA
A ile birlikte kullanıldığında, RecursiveDirectoryIterator
sadece dosya adını değil, tüm yol adını görüntüler. Gerisi iyi görünüyor. Bunun nedeni, dosya adlarının SplFileInfo
. Bunlar, bunun yerine temel adı olarak görüntülenmelidir. İstenen çıktı şu şekildedir:
/// Solved ///
[tree]
├ dirA
│ ├ dirB
│ │ └ fileD
│ ├ fileB
│ └ fileC
└ fileA
İle kullanılabilecek bir dekoratör sınıf oluşturun RecursiveTreeIterator
yerine RecursiveDirectoryIterator
. Yol SplFileInfo
adı yerine akımın temel adını sağlamalıdır . Son kod parçası daha sonra şöyle görünebilir:
$lines = new RecursiveTreeIterator(
new DiyRecursiveDecorator($dir)
);
$unicodeTreePrefix($lines);
echo "[$path]\n", implode("\n", iterator_to_array($lines));
Bu parçalar $unicodeTreePrefix
, Ek: Kendin Yap: RecursiveTreeIterator
İş Satırını Satır Satır Yapın'daki özün bir parçasıdır . .
RecursiveIteratorIterator
çünkü bu diğer türlerle ortaktır, ancak gerçekte nasıl çalıştığına dair bazı teknik bilgiler verdim. Bence örnekler de farklılıklar gösterir: yineleme türü olan ikisi arasındaki temel fark. Onu biraz farklı bir şekilde satın aldığınız yineleme türünü satın alırsanız hiçbir fikrim yok, ancak IMHO yinelemenin semantik türleriyle kolay değil.
Farkı nedir
IteratorIterator
veRecursiveIteratorIterator
?
Bu iki yineleyici arasındaki farkı anlamak için, önce kullanılan adlandırma kurallarını ve "özyinelemeli" yineleyicilerle ne demek istediğimizi biraz anlamak gerekir.
PHP, ArrayIterator
ve gibi "özyinelemeli" olmayan yineleyiciler içerir FilesystemIterator
. Ayrıca RecursiveArrayIterator
ve gibi "özyinelemeli" yineleyiciler de vardır RecursiveDirectoryIterator
. İkincisi, derinlemesine derinlemesine araştırılmalarını sağlayan yöntemlere sahipken, ilki yoktur.
Bu yineleyicilerin örnekleri kendi başlarına döngü oluşturduğunda, özyinelemeli olanlar bile, alt dizinlere sahip iç içe geçmiş bir dizi veya dizin üzerinde döngü oluştursa bile, değerler yalnızca "üst" düzeyden gelir.
Özyinelemeli yineleyiciler özyinelemeli davranış (aracılığıyla , ) uygular ancak bundan yararlanmazlar .hasChildren()
getChildren()
Yinelemeli yineleyicileri "yinelemeli" yineleyiciler olarak düşünmek daha iyi olabilir, yinelemeli yineleme yeteneğine sahiptirler, ancak bu sınıflardan birinin bir örneğini basitçe yinelemek bunu yapmayacaktır. Özyinelemeli davranıştan yararlanmak için okumaya devam edin.
RecursiveIteratorIterator
Oyun burada devreye giriyor. Normal, düz bir döngüde yapının derinliklerine inecek şekilde "tekrarlanabilir" yineleyicileri nasıl çağıracağına dair bilgiye sahiptir. Özyinelemeli davranışı eyleme geçirir. Esasen, yineleyicideki değerlerin her birinin üzerinden geçme, tekrarlanacak "çocuklar" olup olmadığına bakma ve bu çocuk koleksiyonlarına girip çıkma işini yapar. Bir örneğini RecursiveIteratorIterator
bir foreach'a yapıştırırsınız ve o yapının içine dalar, böylece sizin zorunda kalmazsınız.
Eğer RecursiveIteratorIterator
kullanılmamışsa, özyinelemeli davranıştan yararlanmak için kendi özyinelemeli döngülerinizi yazmanız, "özyinelemeli" yineleyicilere karşı kontrol etmeniz hasChildren()
ve kullanmanız gerekir getChildren()
.
Yani bu kısa bir genel bakış RecursiveIteratorIterator
, nasıl farklıdır IteratorIterator
? Temelde aynı türden bir soruyu soruyorsunuz: Bir kedi yavrusu ile ağaç arasındaki fark nedir? Her ikisinin de aynı ansiklopedide (veya yineleyiciler için el kitabında) yer alması, ikisi arasında kafanızın karışması gerektiği anlamına gelmez.
İşi, IteratorIterator
herhangi bir Traversable
nesneyi alıp Iterator
arayüzü tatmin edecek şekilde sarmaktır . Bunun bir kullanımı, yineleyici olmayan nesneye yineleyiciye özgü davranışı uygulayabilmektir.
Pratik bir örnek vermek gerekirse, DatePeriod
sınıf Traversable
bir Iterator
. Bu nedenle, değerleri üzerinden döngü yapabiliriz, foreach()
ancak normalde yineleyici ile yaptığımız diğer şeyleri, örneğin filtreleme gibi yapamayız.
GÖREV : Önümüzdeki dört haftanın Pazartesi, Çarşamba ve Cuma günleri arasında döngü yapın.
Evet, bu döngü içinde- foreach
üzerinden DatePeriod
ve kullanarak bir önemsizdir if()
; ama bu örneğin amacı bu değil!
$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) { … }
Yukarıdaki kod parçası çalışmayacaktır çünkü arayüz CallbackFilterIterator
uygulayan bir sınıf örneği beklemektedir , ancak bu çalışmayacaktır . Ancak, olduğu için bu gereksinimi kullanarak kolayca karşılayabiliriz .Iterator
DatePeriod
Traversable
IteratorIterator
$period = new IteratorIterator(new DatePeriod(…));
Gördüğünüz gibi, bunun yineleyici sınıflar üzerinde yineleme veya özyineleme ile hiçbir ilgisi yoktur ve burada IteratorIterator
ve arasındaki fark yatmaktadır RecursiveIteratorIterator
.
RecursiveIteraratorIterator
bir RecursiveIterator
("tekrarlanabilir" yineleyici) üzerinde yineleme yapmak , mevcut özyinelemeli davranışı kullanmak içindir.
IteratorIterator
Iterator
yineleyici olmayan Traversable
nesnelere davranış uygulamak içindir .
IteratorIterator
için doğrusal sıra kastetmek standart tip sadece Traversable
nesnelere? Olduğu foreach
gibi onsuz kullanılabilenler ? Ve daha da ötesi, bir RecursiveIterator
her zaman a Traversable
değil ve bu nedenle sadece IteratorIterator
değil, aynı zamanda RecursiveIteratorIterator
her zaman " Iterator
yineleyici olmayan, Gezilebilir nesnelere davranış uygulamak için" mi? (Şimdi foreach
yineleyici türü arabirim uygulayan konteyner nesnelerine yineleyici nesnesi aracılığıyla yineleme türünü uyguladığını söyleyebilirim , bu nedenle bunlar her zaman yineleyici kapsayıcı nesnelerdir Traversable
)
IteratorIterator
tamamen Traversable
nesneleri bir Iterator
. Daha fazlası yok . Görünüşe göre bu terimi daha genel olarak uyguluyorsunuz.
Recursive
in RecursiveIterator
, davranışı ima ediyor, oysa daha uygun bir isim yeteneği tanımlayan bir isim olurdu RecursibleIterator
.
İle kullanıldığında iterator_to_array()
, RecursiveIteratorIterator
tüm değerleri bulmak için diziyi özyinelemeli olarak gezer. Orijinal diziyi düzleştireceği anlamına gelir.
IteratorIterator
orijinal hiyerarşik yapıyı koruyacaktır.
Bu örnek size farkı açıkça gösterecektir:
$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))
eşdeğerdir new ArrayIterator($array)
olduğunu, dış IteratorIterator
hiçbir şey yapmıyor. Dahası, çıktının düzleştirilmesinin hiçbir ilgisi yoktur iterator_to_array
- sadece yineleyiciyi bir diziye dönüştürür. Düzleştirme, RecursiveArrayIterator
kendi iç yineleyicisinde gezinme biçiminin bir özelliğidir .
RecursiveDirectoryIterator, sadece dosya adını değil, tüm yol adını görüntüler. Gerisi iyi görünüyor. Bunun nedeni, dosya adlarının SplFileInfo tarafından üretilmesidir. Bunlar, bunun yerine temel adı olarak görüntülenmelidir. İstenen çıktı şu şekildedir:
$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";
}
}
çıktı:
tree
├ dirA
│ ├ dirB
│ │ └ fileD
│ ├ fileB
│ └ fileC
└ fileA