Arrays elegant mit PHP filtern

Ich bin’s mal wieder und möchte Euch über eine elegante Möglichkeit informieren, die ich in den letzten Wochen auch des öfteren für meine Kunden benötigte, um Datenmengen schnell und unkompliziert zu filtern. Zunächst einmal ein einfaches Beispiel, wie man Elemente einer beliebigen Menge filtern kann.

$foo = array('Marcel', 'Johannes', 'Melanie', 'Hendrik');
foreach ($foo as $key => $value) {
    if (strpos($value, 'M') === 0) {
        print $value . "\n";
    }
}

In diesem kleinen Beispiel wenden wir eine Filterregel direkt in einer Schleife an, mit der wir die einzelnen Elemente einer Menge durchlaufen. Funktioniert soweit auch ganz gut. In einem objektorientierten System kann sowas aber schnell unübersichtlich und unpraktisch werden, wenn es darum geht Filterregeln zu erweitern oder auszutauschen.

Zum Glück gibt es die SPL in PHP. Die Standard PHP Library umfasst jede Menge nützliche Klassen, die uns in so einem Fall weiter helfen können. Unter anderen ist hier auch das FilterIterator Objekt enthalten, mit dem wir elegant Elemenge einer Menge filtern können. Mit dem FilterIterator Objekt sind wir in der Lage Iterator Objekte der SPL zu kombinieren. Der FilterIterator nimmt hierbei die Rolle des äußeren Iterators ein, der einen innteren Iterator kontrolliert. Als würde man einen Zaun um eine Schafsherde ziehen, der nur die rot markierten Schafe nach außen lässt. Zunächst ein kleines Beispiel:

class NameFilterIterator extends FilterIterator {

    protected $filter = null;

    public function __construct(Iterator $iterator, $filter) {
        parent::__construct($iterator);
        $this->filter = $filter;
    }

    public function accept() {
        $current = $this->getInnerIterator()->current();

        if (strpos($current, $this->filter) === 0) {
            return true;
        }

        return false;
    }
}

$foo = new ArrayIterator(array('Marcel', 'Johannes', 'Johanna', 'Melanie'));
$iterator = new NameFilterIterator($foo, 'M');

foreach ($iterator as $key => $value) {
    echo $value . "
";
}

In diesem Beispiel schreiben wir zunächst unsere Klasse NameFilterIterator, die auf der abstrakten Klasse FilterIterator aufbaut. Unsere Klasse filtert dann die Elemente des inneren Iterators, der als Objekt dem Konstruktor übergeben wird. In unserem konkreten Beispiel nutzen wir einen einfachen ArrayIterator. Mit der Methode $this->getInnerIterator()->current() können wir auf jedes Element des inneren Iterators zugreifen. In der Methode accept tun wir genau das und filtern jedes Element nach dem übergebenen Filter. In unserem Beispiel wollen wir alle Namen ermitteln, die mit einem M beginnen. Beginnt ein Name nicht mit dem Buchstaben M, gibt die Methode accept einfach ein false zurück und das entsprechende Element wird nicht ausgegeben. In der foreach Schleife werden dann nur die Namen ausgegeben, die wirklich mit einem M beginnen. Zauberei!
Mit dem FilterIterator haben wir also eine Klasse, die es uns erlaubt die Filterregeln schnell anzupassen. Ich komme hier noch mal auf das Beispiel zurück. Möchten wir z.B. nur die Namen mit einem J ausgeben, übergeben wir einfach ein J an unsere NameFilterIterator Klasse. Bei einer einfachen Schleife müssten wir diese komplett neu programmieren. Das will ja niemand. Ein weiterer Vorteil ist, dass man unsere NameFilterIterator Klasse auch als Basis für eine Kindklasse nehmen könnte, um die Filterregel zu erweitern. Wir sind also komplett flexibel und darüber hinaus noch verdammt schnell.

Ich liebe die SPL.

1 Gedanke zu „Arrays elegant mit PHP filtern“

  1. We are a gaggle of volunteers and opening a brand
    new scheme in our community. Your site provided us with helpful info
    to work on. You have performed a formidable process and our entire
    community shall be thankful to you.

    Antworten

Kommentar verfassen

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.