Что такое итератор (Iterator) в PHP?

«Что такое итератор (Iterator) в PHP?» — вопрос из категории PHP Core, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Итератор — это объект, который позволяет последовательно обходить элементы коллекции (например, массива, объекта, результата запроса) без необходимости знать её внутреннее устройство. В PHP итераторы реализуют встроенный интерфейс Iterator или IteratorAggregate.

Основные методы интерфейса Iterator:

  • current(): mixed — возвращает текущий элемент.
  • key(): mixed — возвращает ключ текущего элемента.
  • next(): void — перемещает указатель вперёд к следующему элементу.
  • rewind(): void — сбрасывает указатель на первый элемент.
  • valid(): bool — проверяет, существует ли текущая позиция.

Практический пример — обход большого файла без загрузки в память:

class LargeFileIterator implements Iterator {
    private $fileHandle;
    private $currentLine;
    private $lineNumber = 0;

    public function __construct(string $filePath) {
        if (!file_exists($filePath)) {
            throw new RuntimeException("File not found: $filePath");
        }
        $this->fileHandle = fopen($filePath, 'r');
        if (!$this->fileHandle) {
            throw new RuntimeException("Could not open file: $filePath");
        }
    }

    public function rewind(): void {
        rewind($this->fileHandle);
        $this->currentLine = fgets($this->fileHandle);
        $this->lineNumber = 0;
    }

    public function current(): string {
        return $this->currentLine;
    }

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

    public function next(): void {
        $this->currentLine = fgets($this->fileHandle);
        $this->lineNumber++;
    }

    public function valid(): bool {
        return $this->currentLine !== false;
    }

    public function __destruct() {
        if ($this->fileHandle) {
            fclose($this->fileHandle);
        }
    }
}

// Использование
$logIterator = new LargeFileIterator('/var/log/app.log');
foreach ($logIterator as $lineNumber => $line) {
    if (str_contains($line, 'ERROR')) {
        echo "[$lineNumber] $line";
    }
}
// Файл читается построчно, не загружаясь целиком в память.

Интерфейс IteratorAggregate упрощает создание итераторов, требуя реализации только одного метода getIterator(), который должен возвращать объект Iterator. Все встроенные классы, реализующие Traversable (как ArrayObject), могут использоваться в цикле foreach.