Başka Yineleyiciyi sonuçlarından yeni yineleyici oluşturma

2 Cevap php

Ben PHP 5 etkili Yineleyicilerde kullanarak etrafında başımı almak için çalışıyorum, ve net iyi örnekler bir sürü olmadan, o biraz zor olduğunu kanıtlamaktadır bulunuyor.

Ben bir dizin üzerinde döngü çalışıyor, ve tanımlanmış sınıflar aramak için içindeki tüm (php) dosyalarını okuma ediyorum. Ne zaman yapmak istediğiniz bir ilişkisel dizi anahtarları, değerleri olarak dosya yolları gibi sınıf isimleri ile döndü olması.

By using a RecursiveDirectoryIterator(), I can recurse through directories. By passing this into a RecursiveIteratorIterator, I can retrieve the contents of the directory as a single dimensional iterator. By then using a filter on this, I can filter out all the directories, and non-php files which will just leave me the files I want to consider.

Ne şimdi yapmak istediğiniz başka bir yineleyici (uygun olurdu emin değilim), içine bu yineleyici geçmek mümkün olan her girişin üzerinden döngüler zaman, o bir ana diziye birleştirmek için gereken bir dizi almak olabilir böyle.

Açıklamak için biraz karmaşık, bu nedenle buraya bir kod örneği var:

// $php_files now represents an array of SplFileInfo objects representing files under $dir that match our criteria
$php_files = new PhpFileFilter(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)));

class ClassDetector extends FilterIterator {
    public function accept() {
        $file = $this->current(); // get the current item, which will be an SplFileInfo object

        // Match all the classes contained within this file
        if (preg_match($regex, $file->getContents(), $match)) {
            // Return an assoc array of all the classes matched, the class name as key and the filepath as value
            return array(
                'class1' => $file->getFilename(),
                'class2' => $file->getFilename(),
                'class3' => $file->getFilename(),
            );
        }
    }
}

foreach (new ClassDetector($php_files) as $class => $file) {
    print "{$class} => {$file}\n";
}

// Expected output:
// class1 => /foo.php
// class2 => /foo.php
// class3 => /foo.php
// class4 => /bar.php
// class5 => /bar.php
// ... etc ...

Bu örnekte de görebileceğiniz gibi, ben tür biliyorum tamamen yanlış kullanımıdır FilterIterator için accept () yöntemini kaçırma ediyorum - ama ben sadece bir fonksiyon çağrılacak istiyorum nasıl göstermek için sadece bir örnek olarak kullanabilirsiniz , ve bir ana diziye birleştirilmiş bir dizi dönmek için.

Şu anda ben bu yaptıklarını gibi görünüyor çünkü ben RecursionIterators birini kullanmak zorunda gidiyorum, ama ben iki farklı yöntem (hasChildren () ve getChildren (kullanma fikri düşkün değilim düşünüyorum )) hedefe ulaşmak için.

Kısacası, ben tanımlamaya çalışıyorum hangi Iterator ben kullanmak (ya da genişletmek) bir tek boyutlu bir dizi üzerinden geçmek için (?) Nesnelerin almak için, ve usta bir içine çıkan dizi birleştirmek ve geri alabilirsiniz .

Ben bu etrafında birkaç diğer yollar gibi bir şey ala, olduğunu fark:

$master = array();
foreach($php_files as $file) {
    if (preg_match($regex, $file->getContents(), $match)) {
        // create $match_results
        $master = array_merge($master, $match_results);
    }
}

ama bu Yineleyicilerde kullanarak amacı yendi ve bir çözüm olarak ya da çok şık değil.

Her neyse, ben yeterince iyi izah ettik umuyoruz. Çok önceden ve cevaplar için bu okuma için teşekkürler :)

2 Cevap

Doğru, ben sonunda kafamın etrafında başardı. Ben giriş yineleyici aslında çocuk sonuç getirici çünkü ardışık bir yineleyici kullanmak zorunda kaldı, ve ben zaten bir Iterasyon üzerinde döngü işlevsellik vardı IteratorIterator uzatıldı.

Her neyse, burada bu başkasının olur her ihtimale karşı, bir kod örneği var. Bu (zaten bir DirectoryIterator sonucudur) SplFileInfo nesneleri bir dizi ilettik varsayar.

class
    ClassMatcher
extends
    IteratorIterator
implements
    RecursiveIterator
{

    protected $matches;

    public function hasChildren() {
        return preg_match_all(
            '#class (\w+)\b#ism',
            file_get_contents($this->current()->getPathname()),
            $this->matches
        );
    }

    public function getChildren() {
        $classes = $this->matches[1];

        return new RecursiveArrayIterator(
            array_combine(
                $classes,                                                       // class name as key
                array_fill(0, count($classes), $this->current()->getPathname()) // file path as value
            )
        );
    }
}

Bir keresinde benzer bir şey yaptım. source is right here ve kolayca anlaşılabilir olduğuna inanıyorum. Eğer herhangi bir sorun varsa lütfen bana bildirin.

Ana fikir SplFileInfo uzatmak ve daha sonra kaynak kodu hakkında bilgi almak için RecursiveIteratorIterator::setInfoClass($className); kullanmaktır. Ben ana döngüsü içinde uzantısı tarafından filtrelemek sonra geri verdi gerçi sadece PHP dosyalarını ayrıştırma için bir filtre güzel olabilir.