Start · Sprachen · PHP · Referenz · ParentIterator

ParentIterator

Klasse

Filtert bei einer rekursiven Iteration nur diejenigen Elemente heraus, die selbst Kinder besitzen (d. h. <code>hasChildren()</code> liefert <code>true</code>).

seit PHP 5.1.0 Kategorie: oop

Signatur

class ParentIterator extends RecursiveFilterIterator implements RecursiveIterator, OuterIterator, Traversable, Iterator

Beschreibung

ParentIterator ist eine spezialisierte Unterklasse von RecursiveFilterIterator, die automatisch nur solche Elemente durchlässt, für die hasChildren() den Wert true zurückgibt. Damit lässt sich eine Baumstruktur auf Knoten reduzieren, die mindestens ein Kind besitzen – also auf "innere" Knoten, keine Blätter.

Typischerweise wird ParentIterator zusammen mit RecursiveIteratorIterator genutzt, um verschachtelte Datenstrukturen (z. B. RecursiveArrayIterator über mehrdimensionale Arrays) zu traversieren und dabei ausschließlich die Eltern-Ebenen anzuzeigen oder weiterzuverarbeiten.

Die Klasse überschreibt accept() so, dass sie intern hasChildren() des gekapselten Iterators aufruft. Eigene Filterlogik kann durch Ableitung und Überschreiben von accept() ergänzt werden, wobei der ursprüngliche hasChildren()-Check erhalten bleiben sollte, wenn nur Eltern-Filterung gewünscht ist.

Besonders nützlich ist ParentIterator bei der Darstellung oder Auswertung von Verzeichnisbäumen, Kategoriehierarchien oder beliebig verschachtelten Array-Strukturen, wenn Blatt-Knoten ignoriert werden sollen.

Parameter

Name Typ Default Beschreibung
$iterator Pflicht RecursiveIterator Ein RecursiveIterator, dessen Elemente gefiltert werden sollen. Nur Elemente, für die hasChildren() true liefert, werden von ParentIterator weitergegeben.

Rückgabewert

Typ

Beispiele

Nur Eltern-Knoten eines mehrdimensionalen Arrays ausgeben

<?php
$data = [
    'Obst' => [
        'Äpfel' => ['Gala', 'Braeburn'],
        'Birnen' => ['Williams'],
    ],
    'Gemüse' => [
        'Wurzelgemüse' => ['Karotte', 'Pastinake'],
    ],
    'Sonstiges', // Blatt-Knoten – wird gefiltert
];

$recursive = new RecursiveArrayIterator($data);
$parentOnly = new ParentIterator($recursive);

foreach (new RecursiveIteratorIterator($parentOnly, RecursiveIteratorIterator::SELF_FIRST) as $key => $value) {
    echo $key . PHP_EOL;
}
Obst Äpfel Birnen Gemüse Wurzelgemüse

Verzeichnisbaum: Nur Ordner (keine Dateien) auflisten

<?php
$path = new RecursiveDirectoryIterator(
    '/var/www',
    FilesystemIterator::SKIP_DOTS
);

$parentOnly = new ParentIterator($path);

$iterator = new RecursiveIteratorIterator(
    $parentOnly,
    RecursiveIteratorIterator::SELF_FIRST
);

foreach ($iterator as $item) {
    // Nur Verzeichnisse werden gezeigt, weil RecursiveDirectoryIterator
    // für Dateien kein hasChildren() = true liefert
    echo str_repeat('  ', $iterator->getDepth())
        . $item->getFilename()
        . DIRECTORY_SEPARATOR
        . PHP_EOL;
}

// Wichtig · Fallstricke

Wichtig: ParentIterator filtert auf Basis von hasChildren() des gekapselten Iterators. Bei RecursiveArrayIterator bedeutet dies: Ein Element muss ein Array oder ein Traversable-Objekt sein, damit es als Eltern-Knoten gilt. Skalare Werte (Strings, Zahlen) werden herausgefiltert.

Beim Einsatz mit RecursiveIteratorIterator im Modus SELF_FIRST oder CHILD_FIRST ist zu beachten, dass der ParentIterator selbst nur die äußerste Ebene filtert; das rekursive Hineinsteigen und der Filter auf tieferen Ebenen werden durch die Kombination von RecursiveIteratorIterator und den getChildren()-Aufrufen gesteuert, die ihrerseits wieder ParentIterator-Instanzen zurückgeben.

Die Methode getChildren() gibt automatisch einen neuen ParentIterator zurück, der den Kind-Iterator des aktuellen Elements kapselt – der Filter gilt also rekursiv auf allen Ebenen.