Start · Sprachen · PHP · Referenz · SeekableIterator

SeekableIterator

Interface

Erweitert <code>Iterator</code> um die Methode <code>seek()</code>, mit der direkt zu einer bestimmten Position im Iterator gesprungen werden kann.

seit PHP 5.1.0 Kategorie: oop

Signatur

interface SeekableIterator extends Iterator

Beschreibung

SeekableIterator ist ein eingebautes PHP-Interface, das das Iterator-Interface um die Methode seek(int $offset) ergänzt. Damit kann der interne Zeiger des Iterators direkt auf eine beliebige Position gesetzt werden, ohne alle vorherigen Elemente einzeln zu durchlaufen.

Das Interface ist immer dann sinnvoll, wenn auf Datenstrukturen wahlfreier Zugriff benötigt wird – etwa bei großen Datensätzen, paginierten Ergebnissen oder Dateizugriffen, bei denen das sequenzielle Durchlaufen bis zur Zielposition ineffizient wäre. PHP's eingebaute Klasse ArrayIterator implementiert dieses Interface beispielsweise bereits.

Eigene Klassen, die SeekableIterator implementieren, müssen alle Methoden von Iterator (current(), key(), next(), rewind(), valid()) sowie die zusätzliche Methode seek(int $offset) bereitstellen. Wird eine ungültige Position übergeben, sollte eine OutOfBoundsException geworfen werden.

Durch die Implementierung von SeekableIterator kann eine Klasse auch mit PHP-Funktionen wie iterator_to_array() verwendet werden und lässt sich in foreach-Schleifen einsetzen, bietet jedoch zusätzlich den direkten Positionszugriff.

Beispiele

Eigene Klasse mit SeekableIterator implementieren

<?php
class NumberRange implements SeekableIterator
{
    private int $position = 0;
    private array $data;

    public function __construct(int $start, int $end)
    {
        $this->data = range($start, $end);
    }

    public function seek(int $offset): void
    {
        if (!isset($this->data[$offset])) {
            throw new OutOfBoundsException("Ungültige Position: $offset");
        }
        $this->position = $offset;
    }

    public function current(): int
    {
        return $this->data[$this->position];
    }

    public function key(): int
    {
        return $this->position;
    }

    public function next(): void
    {
        $this->position++;
    }

    public function rewind(): void
    {
        $this->position = 0;
    }

    public function valid(): bool
    {
        return isset($this->data[$this->position]);
    }
}

$range = new NumberRange(1, 10);

// Direkt zur Position 4 springen (Wert: 5)
$range->seek(4);
echo $range->current() . PHP_EOL;

// Weiter iterieren ab Position 4
foreach ($range as $key => $value) {
    echo "[$key] => $value" . PHP_EOL;
    if ($key === 6) break;
}
5 [4] => 5 [5] => 6 [6] => 7

ArrayIterator als eingebaute SeekableIterator-Implementierung

<?php
$iterator = new ArrayIterator(['Apfel', 'Birne', 'Kirsche', 'Mango', 'Orange']);

// Direkt zum dritten Element (Index 2) springen
$iterator->seek(2);
echo $iterator->current() . PHP_EOL; // Kirsche

// Zum letzten Element springen
$iterator->seek(4);
echo $iterator->current() . PHP_EOL; // Orange

// Ungültige Position auslösen
try {
    $iterator->seek(99);
} catch (OutOfBoundsException $e) {
    echo 'Fehler: ' . $e->getMessage() . PHP_EOL;
}
Kirsche Orange Fehler: Seek position 99 is out of range

// Wichtig · Fallstricke

OutOfBoundsException werfen: Laut PHP-Konvention sollte die seek()-Methode eine OutOfBoundsException werfen, wenn die angegebene Position außerhalb des gültigen Bereichs liegt. Dies ist zwar nicht durch das Interface erzwungen, aber eine wichtige Best Practice für konsistentes Fehlerhandling.

Verhalten nach seek(): Nach dem Aufruf von seek() zeigt der interne Zeiger auf die angegebene Position. Ein anschließendes foreach beginnt daher nicht zwingend am Anfang – rewind() wird bei foreach jedoch automatisch aufgerufen und setzt den Zeiger zurück auf Position 0.

Abgrenzung zu ArrayAccess: SeekableIterator ist für sequenziellen Zugriff mit Sprungmöglichkeit gedacht. Für vollständigen wahlfreien Lese- und Schreibzugriff per Index-Notation ($obj[2]) sollte stattdessen oder zusätzlich das Interface ArrayAccess implementiert werden.