Signatur
Beschreibung
RecursiveFilterIterator erweitert FilterIterator um Rekursionsfähigkeit und implementiert das RecursiveIterator-Interface. Er ermöglicht es, einen rekursiven Iterator (z. B. RecursiveArrayIterator oder RecursiveDirectoryIterator) zu filtern, wobei die Baumstruktur erhalten bleibt. Konkrete Unterklassen müssen lediglich die abstrakte Methode accept() implementieren, die entscheidet, ob das aktuelle Element behalten (true) oder übersprungen (false) werden soll.
Der wesentliche Unterschied zu einem einfachen FilterIterator liegt in der Methode getChildren(): Sie gibt eine neue Instanz derselben Filterklasse zurück, die um den Kind-Iterator gewickelt ist. Dadurch wird die Filterbedingung automatisch auch auf alle Ebenen des Baums angewendet, wenn man den Iterator z. B. mit RecursiveIteratorIterator traversiert.
Ein typischer Anwendungsfall ist das Durchsuchen von Verzeichnisstrukturen (z. B. nur bestimmte Dateiendungen anzeigen) oder das Filtern verschachtelter Array-Strukturen nach beliebigen Kriterien, ohne die Baumform des Ergebnisses zu verlieren.
Achtung: Standardmäßig filtert RecursiveFilterIterator nur auf der aktuellen Ebene. Sollen Kind-Knoten erreichbar sein, deren Elternknoten die Bedingung nicht erfüllen, muss accept() für Container-Elemente gegebenenfalls immer true zurückgeben oder die Logik entsprechend angepasst werden.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $iterator Pflicht | RecursiveIterator | Der rekursive Iterator, dessen Elemente gefiltert werden sollen. Muss das RecursiveIterator-Interface implementieren, z. B. RecursiveArrayIterator oder RecursiveDirectoryIterator. |
Rückgabewert
Beispiele
Dateien nach Endung in Verzeichnisbaum filtern
<?php
class PhpFileFilter extends RecursiveFilterIterator
{
public function accept(): bool
{
// Verzeichnisse immer durchlassen, damit Unterordner erreichbar bleiben
if ($this->current()->isDir()) {
return true;
}
// Nur .php-Dateien akzeptieren
return $this->current()->getExtension() === 'php';
}
}
$dirIterator = new RecursiveDirectoryIterator(
__DIR__,
RecursiveDirectoryIterator::SKIP_DOTS
);
$filter = new PhpFileFilter($dirIterator);
$iterator = new RecursiveIteratorIterator(
$filter,
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $file) {
if (!$file->isDir()) {
echo $file->getPathname() . PHP_EOL;
}
}
Verschachteltes Array nach Wert-Kriterium filtern
<?php
class EvenNumberFilter extends RecursiveFilterIterator
{
public function accept(): bool
{
$current = $this->current();
// Arrays (Knoten) immer durchlassen
if (is_array($current)) {
return true;
}
// Nur gerade Zahlen akzeptieren
return is_int($current) && $current % 2 === 0;
}
}
$data = [
1, 2, 3,
'nested' => [4, 5, 6, 7, 8],
9, 10
];
$arrayIterator = new RecursiveArrayIterator($data);
$filter = new EvenNumberFilter($arrayIterator);
$iterator = new RecursiveIteratorIterator($filter);
foreach ($iterator as $key => $value) {
echo "$key => $value" . PHP_EOL;
}
// Wichtig · Fallstricke
Wichtiger Fallstrick: Wenn accept() für ein Container-Element (ein Element, das Kinder hat) false zurückgibt, sind dessen Kinder mit RecursiveIteratorIterator nicht erreichbar, da hasChildren() intern ebenfalls die Filterung berücksichtigt. Sollen Kinder von nicht akzeptierten Eltern trotzdem durchsucht werden, muss die Logik entsprechend angepasst oder ein eigener RecursiveIteratorIterator mit überschriebenem callHasChildren() genutzt werden.
RecursiveFilterIterator ist eine abstrakte Klasse – sie kann nicht direkt instanziiert werden. Es muss immer eine konkrete Unterklasse erstellt werden, die accept(): bool implementiert.
Die Methode getChildren() erzeugt standardmäßig eine neue Instanz der jeweiligen Unterklasse via new static(). Werden im Konstruktor der Unterklasse zusätzliche Parameter benötigt, muss getChildren() entsprechend überschrieben werden.