ArrayIterator: Einen Schritt zurück

Wer schon mal mit dem nativen PHP ArrayIterator Objekt gearbeitet hat, wird unter Umständen auch schon mal festgestellt haben, dass dieses Objekt über keine einfache Methode verfügt, um einen Schritt zurück in der aktuellen Abfolge von Einträgen in einem Array zu machen. Ganz nach dem Motto Vorwärts immer – rückwärts nimmer. Ich stand heute vor dem Problem, dass ich diesen einen Schritt zurück mit einem Iterator machen musste. Heute gibt es also eine Lösung, um in einem Iterator Objekt auch einen Schritt zurück machen zu können.

Gehen wir einfach mal davon aus, dass wir folgendes Array haben:

$aList = [
    [
        'id' => 1,
        'name' => 'Sarah',
    ],
    [
        'id' => 2,
        'name' => 'Marcel',
    ],
    [
        'id' => 3,
        'name' => 'Steffen',
    ],
];

Wie ihr seht, gibt es in diesem Array drei Einträge. Jeder dieser Einträge ist ein weiteres Array mit den Eigenschaften ID und Name. Also eigentlich eine ganz normale Menge, wie man sie z.B. aus Datenbanken ermittelt. Als nächstes benötigen wir eine abgewandelte Version des ArrayIterator Objektes, welches eine prev() Methode besitzen soll. Folgend eine denkbar einfache Version einer solchen Methode.

class MyArrayIterator extends ArrayIterator {
    public function prev() {
        $prev = $this->key() - 1;
        if ($prev < 0 || $prev > ($this->count() - 1)) {
            throw new OutOfRangeException('Die Position liegt nicht innerhalb des Arrays');
        }
        $this->seek($prev);
    }
}

Wir haben jetzt also eine prev() Methode. Diese Methode setzt den internen Counter um eins zurück. Liegt der Schlüssel des Arrays außerhalb der Dimensionen des Arrays, wird eine OutOfRangeException geworfen. Ist der neu ermittelte Schlüssel valide, setzen wir den internen Zeiger des Arrays auf die ermittelte Position. Führen wir den Code also einfach mal aus.

$oArray = new ArrayObject($aList);
$oArray->setIteratorClass('MyArrayIterator');

$oIterator = $oArray->getIterator();
$oIterator->seek(2);
$oIterator->prev();

// Ausgabe: array(2) { ["id"]=> int(2), ["name"] => string(6) "Marcel" }
var_dump($oIterator->current());

Zur Veranschaulichung bilden wir in diesem Beispiel aus unserem einfachen Array ein ArrayObject und weisen diesem unseren neuen ArrayIterator mit der prev() Methode zu. Als nächstes holen wir uns eine Instanz des Iterators und setzen den internen Zeiger auf die zweite Position im Array. Da wir hier immer bei 0 beginnen zu zählen, ist dies die letzte Position im Array. Mit einem Schritt zurück befinden wir uns genau in der Mitte unseres Arrays und mit der current() Methode geben wir uns dann einfach den Wert dieser Position aus.

Was kann dieses Beispiel nicht?

Bei diesem Beispiel wird mit einem einfachen Array mit einem fortlaufenden Index gearbeitet. Wenn die Schlüssel des Arrays Strings oder ungeordnet sein sollten, funktioniert das gezeigte Beispiel schon nicht mehr, da es einfach von einem fortlaufenden, sortierten Index ausgeht. Aber auch für Arrays mit einem Index aus Strings oder für Arrays mit einem unsortierten Index gibt es eine Lösung. Vielleicht gibt es dazu ja etwas in einem der kommenden Freaky Friday Posts? Wir werden sehen.

Haben wir also wieder was gelernt! 😉

Bildquelle: Pixabay – ivanacoi / CC0 Public Domain

Kommentar verfassen

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